diff --git a/.github/workflows/native-server.yml b/.github/workflows/native-server.yml new file mode 100644 index 00000000000..cfbecc08253 --- /dev/null +++ b/.github/workflows/native-server.yml @@ -0,0 +1,402 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT 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: Native Build Server + +on: + push: + branches: [ test*, "*.*.*", 2.x ] + pull_request: + branches: [ 2.x, develop, master ] + paths: + - '.github/workflows/native-server.yml' + - 'server/src/main/resources/META-INF/native-image/**' + workflow_call: + inputs: + repository: + description: 'Repository to check out' + type: string + required: false + default: '' + ref: + description: 'Branch or tag to check out' + type: string + required: false + default: '' + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + build: + name: build & test (file) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ ubuntu-24.04, ubuntu-24.04-arm, macos-26, windows-latest ] + # Note: macos-26 is Apple Silicon (ARM64) only. + # Intel macOS (x86_64) is not supported because GraalVM has + # discontinued updates for that platform. + # https://github.com/graalvm/graalvm-ce-builds/releases/tag/jdk-25.0.1 + env: + USERNAME: seata + PASSWORD: seata + steps: + - name: "Checkout" + uses: actions/checkout@v7.0.0 + with: + repository: ${{ inputs.repository || github.repository }} + ref: ${{ inputs.ref || github.ref }} + - name: "Start MySQL via Docker (Linux only)" + if: runner.os == 'Linux' + shell: sh + run: | + docker run -d --name mysql-test \ + -e MYSQL_ALLOW_EMPTY_PASSWORD=yes \ + -e MYSQL_DATABASE=seata_test_native \ + -p 3306:3306 \ + mysql:8.0 + echo "Waiting for MySQL to be ready..." + for i in $(seq 1 30); do + if docker exec mysql-test mysqladmin ping -h localhost --silent 2>/dev/null; then + echo "MySQL is ready" + docker logs mysql-test --tail 10 + exit 0 + fi + echo "Waiting for MySQL... ($i/30)" + sleep 2 + done + echo "ERROR: MySQL failed to start after 60s" + docker logs mysql-test --tail 50 + exit 1 + - name: "Set up Java JDK" + uses: actions/setup-java@v5.5.0 + with: + distribution: 'graalvm' + java-version: 25 + - name: "Print maven version" + run: ./mvnw -version + - name: "Restore local maven repository cache" + uses: actions/cache/restore@v6.1.0 + id: cache-maven-repository + with: + path: ~/.m2/repository + key: ${{ runner.os }}-${{ runner.arch }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-${{ runner.arch }}-maven- + - name: "Install dependencies" + # test-native-server requires seata-spring-boot-starter + run: ./mvnw -T 4C clean -B -pl server,spring/seata-spring-boot-starter install -DskipTests -am + - name: "Compile native image" + shell: sh + run: | + ./mvnw -T 2C clean -B -pl server package -DskipTests -Pnative spring-boot:process-aot native:compile + rm -rf server/target/*.jar + - name: "Upload binaries" + uses: actions/upload-artifact@v7.0.1 + with: + name: server-native-${{ runner.os }}-${{ runner.arch }} + path: | + server/target/seata-*-* + if-no-files-found: error + - name: "Verify native binary" + shell: sh + env: + SEATA_CONFIG_TYPE: file + SEATA_REGISTRY_TYPE: file + SEATA_STORE_TYPE: file + run: | + ./server/target/seata-server-* & + NATIVE_PID=$! + echo "$NATIVE_PID" > ./seata-native-server.pid + echo "Native binary started with PID=$NATIVE_PID" + sleep 10 + if kill -0 $NATIVE_PID 2>/dev/null; then + echo "Native binary is running normally (PID=$NATIVE_PID)" + else + echo "ERROR: Native binary failed to start or crashed (PID=$NATIVE_PID)" + exit 1 + fi + - name: "Check port 8091 for server in ${{ matrix.os }}" + shell: sh + env: + MAX_RETRIES: 6 + SLEEP_SECONDS: 5 + run: | + NATIVE_PID=$(cat ./seata-native-server.pid) + echo "NATIVE_PID=$NATIVE_PID" + i=1 + while [ $i -le $MAX_RETRIES ]; do + if curl -sSf http://localhost:8091/health >/dev/null 2>&1; then + echo "Port 8091 is responding" + exit 0 + fi + echo "Waiting for port 8091... ($i/$MAX_RETRIES)" + sleep $SLEEP_SECONDS + i=$((i + 1)) + done + echo "ERROR: Port 8091 is not responding after $((MAX_RETRIES * SLEEP_SECONDS)) seconds" + exit 1 + - name: "Start test-native-server app for server in ${{ matrix.os }}" + if: runner.os == 'Linux' + env: + MAX_RETRIES: 12 + SLEEP_SECONDS: 5 + run: | + nohup ./mvnw -e -T 2C -Ptest-native-server -pl test-suite/test-native-server spring-boot:run & + i=1 + while [ $i -le $MAX_RETRIES ]; do + if curl -sSf http://localhost:50180/actuator/health >/dev/null 2>&1; then + echo "Port 50180 is responding" + exit 0 + fi + echo "Waiting for port 50180... ($i/$MAX_RETRIES)" + sleep $SLEEP_SECONDS + i=$((i + 1)) + done + echo "ERROR: Port 50180 is not responding after $((MAX_RETRIES * SLEEP_SECONDS)) seconds" + exit 1 + - name: "Run native tests for server in ${{ matrix.os }}" + if: runner.os == 'Linux' + run: ./mvnw -e -T 2C -Ptest-native-server -pl test-suite/test-native-server clean test + - name: "Capture test reports on failure" + if: failure() && runner.os == 'Linux' + shell: sh + run: | + echo "=== Surefire Test Reports ===" + if [ -d test-suite/test-native-server/target/surefire-reports ]; then + for f in test-suite/test-native-server/target/surefire-reports/*.txt; do + [ -f "$f" ] || continue + echo "" + echo "============================================================" + echo "--- $f ---" + echo "============================================================" + cat "$f" + done + else + echo "No surefire-reports directory found" + fi + - name: "Delete snapshots from the Maven local repository" + shell: sh + run: find ~/.m2/repository -type d -name '*-SNAPSHOT' -print -exec rm -r {} + || true + - name: "Save local maven repository cache" + uses: actions/cache/save@v6.1.0 + if: steps.cache-maven-repository.outputs.cache-hit != 'true' + with: + path: ~/.m2/repository + key: ${{ runner.os }}-${{ runner.arch }}-maven-${{ hashFiles('**/pom.xml') }} + + nacos: + name: test (nacos) + runs-on: ${{ matrix.os }} + env: + MAX_RETRIES: 60 + SLEEP_SECONDS: 30 + strategy: + fail-fast: false + matrix: + os: [ ubuntu-24.04, ubuntu-24.04-arm, macos-26, windows-latest ] + steps: + - name: "Checkout" + uses: actions/checkout@v7.0.0 + with: + repository: ${{ inputs.repository || github.repository }} + ref: ${{ inputs.ref || github.ref }} + - name: "Start MySQL via Docker (Linux only)" + if: runner.os == 'Linux' + shell: sh + run: | + docker run -d --name mysql-test \ + -e MYSQL_ALLOW_EMPTY_PASSWORD=yes \ + -e MYSQL_DATABASE=seata_test_native \ + -p 3306:3306 \ + mysql:8.0 + echo "Waiting for MySQL to be ready..." + for i in $(seq 1 30); do + if docker exec mysql-test mysqladmin ping -h localhost --silent 2>/dev/null; then + echo "MySQL is ready" + docker logs mysql-test --tail 10 + exit 0 + fi + echo "Waiting for MySQL... ($i/30)" + sleep 2 + done + echo "ERROR: MySQL failed to start after 60s" + docker logs mysql-test --tail 50 + exit 1 + - name: "Checkout Nacos" + uses: actions/checkout@v7.0.0 + with: + repository: alibaba/nacos + ref: 3.2.3 + path: nacos + - name: "Build Nacos" + working-directory: nacos + run: ./mvnw install -B -pl bootstrap -DskipTests -am + - name: "Start Nacos" + shell: sh + working-directory: nacos + run: | + nohup ./mvnw -B spring-boot:run -pl bootstrap -Prelease-nacos \ + -Dspring-boot.run.jvmArguments="--add-opens java.base/java.util=ALL-UNNAMED -Dnacos.standalone=true -Dnacos.core.auth.server.identity.key=identity.key -Dnacos.core.auth.server.identity.value=identity.value -Dnacos.core.auth.plugin.nacos.token.secret.key=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg= -Dnacos.core.auth.enabled=false" & + echo "Waiting for Nacos to be ready..." + for i in $(seq 1 30); do + if curl -sSf http://localhost:8080/v3/console/server/state >/dev/null 2>&1; then + echo "Port 8080 is responding" + exit 0 + fi + echo "Waiting for Nacos... ($i/30)" + sleep 2 + done + echo "ERROR: Nacos failed to start after 60s" + docker logs nacos-test --tail 50 + exit 1 + - name: "Set up Java JDK" + uses: actions/setup-java@v5.5.0 + with: + distribution: 'graalvm' + java-version: 25 + - name: "Print maven version" + run: ./mvnw -version + - name: "Restore local maven repository cache" + uses: actions/cache/restore@v6.1.0 + id: cache-maven-repository + with: + path: ~/.m2/repository + key: server-native-nacos-${{ runner.os }}-${{ runner.arch }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + server-native-nacos-${{ runner.os }}-${{ runner.arch }}-maven- + - name: "Install dependencies" + # test-native-server requires seata-spring-boot-starter + shell: sh + run: | + ./mvnw -T 4C clean -B -pl server,spring/seata-spring-boot-starter install -DskipTests -am + rm -rf server/target/*.jar + - name: "Adjust retry timeout for Windows" + if: runner.os == 'Windows' + run: echo "MAX_RETRIES=180" >> $GITHUB_ENV + - name: "Wait for build job" + shell: sh + env: + GH_TOKEN: ${{ github.token }} + run: | + for i in $(seq 1 ${{ env.MAX_RETRIES }}); do + RESULT=$(gh api "repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/jobs" \ + --jq ".jobs[] | select(.name | startswith(\"build & test (file)\") and endswith(\"(${{ matrix.os }})\")) | \"\(.status) \(.conclusion)\"") + if [ -z "$RESULT" ]; then + echo "Build job for ${{ matrix.os }} not found yet... ($i/${{ env.MAX_RETRIES }})" + sleep ${{ env.SLEEP_SECONDS }} + continue + fi + STATUS="${RESULT%% *}" + CONCLUSION="${RESULT##* }" + case "${STATUS}|${CONCLUSION}" in + "completed|success") + echo "Build job for ${{ matrix.os }} completed successfully" + exit 0 + ;; + "completed|failure"|"completed|cancelled"|"completed|skipped") + echo "ERROR: Build job for ${{ matrix.os }} finished with status=${STATUS} conclusion=${CONCLUSION}" + exit 1 + ;; + esac + echo "Build job for ${{ matrix.os }} status=${STATUS}... ($i/${{ env.MAX_RETRIES }})" + sleep ${{ env.SLEEP_SECONDS }} + done + echo "ERROR: Build job for ${{ matrix.os }} did not complete in $(( ${{ env.MAX_RETRIES }} * ${{ env.SLEEP_SECONDS }} )) seconds" + exit 1 + - name: "Download binaries" + uses: actions/download-artifact@v7.0.0 + with: + name: server-native-${{ runner.os }}-${{ runner.arch }} + path: server/target/ + - name: "Fix binary permissions" + shell: sh + run: chmod +x ./server/target/seata-server-* + - name: "Verify native binary" + shell: sh + env: + SEATA_CONFIG_TYPE: nacos + SEATA_CONFIG_NACOS_SERVERADDR: "127.0.0.1:8848" + SEATA_CONFIG_NACOS_NAMESPACE: "" + SEATA_CONFIG_NACOS_GROUP: SEATA_GROUP + SEATA_CONFIG_NACOS_CONTEXTPATH: "" + SEATA_CONFIG_NACOS_USERNAME: "" + SEATA_CONFIG_NACOS_PASSWORD: "" + SEATA_CONFIG_NACOS_ACCESSKEY: "" + SEATA_CONFIG_NACOS_SECRETKEY: "" + SEATA_CONFIG_NACOS_RAMROLENAME: "" + SEATA_CONFIG_NACOS_DATAID: seataServer.properties + SEATA_REGISTRY_TYPE: nacos + SEATA_REGISTRY_PREFERREDNETWORKS: "30.240.*" + SEATA_REGISTRY_IGNOREDINTERFACES: VMware.* + SEATA_REGISTRY_METADATA_WEIGHT: "100" + SEATA_REGISTRY_NACOS_APPLICATION: seata-server + SEATA_REGISTRY_NACOS_SERVERADDR: "127.0.0.1:8848" + SEATA_REGISTRY_NACOS_NAMESPACE: "" + SEATA_REGISTRY_NACOS_GROUP: "SEATA_GROUP" + SEATA_REGISTRY_NACOS_CLUSTER: default + SEATA_REGISTRY_NACOS_CONTEXTPATH: "" + SEATA_REGISTRY_NACOS_USERNAME: "" + SEATA_REGISTRY_NACOS_PASSWORD: "" + SEATA_REGISTRY_NACOS_ACCESSKEY: "" + SEATA_REGISTRY_NACOS_SECRETKEY: "" + SEATA_REGISTRY_NACOS_RAMROLENAME: "" + SEATA_STORE_TYPE: file + run: | + ./server/target/seata-server-* & + NATIVE_PID=$! + echo "$NATIVE_PID" > ./seata-native-server.pid + echo "Native binary started with PID=$NATIVE_PID" + sleep 10 + if kill -0 $NATIVE_PID 2>/dev/null; then + echo "Native binary is running normally (PID=$NATIVE_PID)" + else + echo "ERROR: Native binary failed to start or crashed (PID=$NATIVE_PID)" + exit 1 + fi + - name: "Check port 8091 for server in ${{ matrix.os }}" + shell: sh + env: + MAX_RETRIES: 6 + SLEEP_SECONDS: 5 + run: | + NATIVE_PID=$(cat ./seata-native-server.pid) + echo "NATIVE_PID=$NATIVE_PID" + i=1 + while [ $i -le $MAX_RETRIES ]; do + if curl -sSf http://localhost:8091/health >/dev/null 2>&1; then + echo "Port 8091 is responding" + exit 0 + fi + echo "Waiting for port 8091... ($i/$MAX_RETRIES)" + sleep $SLEEP_SECONDS + i=$((i + 1)) + done + echo "ERROR: Port 8091 is not responding after $((MAX_RETRIES * SLEEP_SECONDS)) seconds" + exit 1 + - name: "Delete snapshots and Nacos from the Maven local repository" + shell: sh + run: | + find ~/.m2/repository -type d -name '*-SNAPSHOT' -print -exec rm -r {} + || true + find ~/.m2/repository -type d -name 'nacos' -print -exec rm -r {} + || true + - name: "Save local maven repository cache" + uses: actions/cache/save@v6.1.0 + with: + path: ~/.m2/repository + key: server-native-nacos-${{ runner.os }}-${{ runner.arch }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.gitignore b/.gitignore index f4ce63bf64a..33ece437870 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,5 @@ Thumbs.db /console/src/main/resources/static/saga-statemachine-designer/ /console/src/main/resources/static/index.html /console/src/main/resources/static/version.json + +__pycache__/ diff --git a/Makefile b/Makefile index 0228bd4b974..50abe26cb32 100644 --- a/Makefile +++ b/Makefile @@ -23,14 +23,26 @@ SHELL := /usr/bin/env bash # matching the target name — make will always execute them regardless of file timestamps) .PHONY: help clean spotless-check spotless-apply checkstyle checkstyle-diff license test \ package-only package \ - install-server-jar install-namingserver-jar \ - install-run-namingserver-native-jar run-namingserver-native-jar \ - install-run-server-jar run-server-jar \ - install-run-server-jar-registry-seata run-server-jar-registry-seata \ + install-server-jar \ + install-namingserver-jar \ + install-run-namingserver-native-jar \ + run-namingserver-native-jar \ + install-run-server-native-file-jar \ + run-server-native-file-jar \ + install-run-server-jar \ + run-server-jar \ + install-run-server-jar-registry-seata \ + run-server-jar-registry-seata \ test-native-namingserver \ + test-native-server \ run-merge-native-namingserver \ - install-namingserver-native package-namingserver-native \ - run-namingserver-native + install-namingserver-native \ + package-namingserver-native \ + run-namingserver-native \ + install-server-native \ + package-server-native \ + run-server-native-file \ + run-server-native-nacos help: ## Show help information @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-34s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) @@ -45,16 +57,52 @@ MVN ?= $(shell command -v mvn >/dev/null 2>&1 && echo "mvn" || echo "./mvnw") MAVEN_ARGS ?= -T 4C -e -B -V NACOS_SERVER_ADDR ?= 127.0.0.1:8848 +NACOS_NAMESPACE ?= +NACOS_GROUP ?= SEATA_GROUP +NACOS_DATAID ?= seataServer.properties +NACOS_USERNAME ?= +NACOS_PASSWORD ?= -# Dynamically resolve the namingserver version from the Maven project (e.g. 2.8.0-SNAPSHOT) +# Shared Nacos environment variables for config (nacos) + registry (nacos) + store (file) mode +define NACOS_MODE_ENV +SEATA_CONFIG_TYPE=nacos \ +SEATA_CONFIG_NACOS_SERVERADDR=$(NACOS_SERVER_ADDR) \ +SEATA_CONFIG_NACOS_NAMESPACE=$(NACOS_NAMESPACE) \ +SEATA_CONFIG_NACOS_GROUP=$(NACOS_GROUP) \ +SEATA_CONFIG_NACOS_CONTEXTPATH= \ +SEATA_CONFIG_NACOS_USERNAME=$(NACOS_USERNAME) \ +SEATA_CONFIG_NACOS_PASSWORD=$(NACOS_PASSWORD) \ +SEATA_CONFIG_NACOS_ACCESSKEY= \ +SEATA_CONFIG_NACOS_SECRETKEY= \ +SEATA_CONFIG_NACOS_RAMROLENAME= \ +SEATA_CONFIG_NACOS_DATAID=$(NACOS_DATAID) \ +SEATA_REGISTRY_TYPE=nacos \ +SEATA_REGISTRY_PREFERREDNETWORKS=30.240.* \ +SEATA_REGISTRY_IGNOREDINTERFACES=VMware.* \ +SEATA_REGISTRY_METADATA_WEIGHT=100 \ +SEATA_REGISTRY_NACOS_APPLICATION=seata-server \ +SEATA_REGISTRY_NACOS_SERVERADDR=$(NACOS_SERVER_ADDR) \ +SEATA_REGISTRY_NACOS_NAMESPACE=$(NACOS_NAMESPACE) \ +SEATA_REGISTRY_NACOS_GROUP=$(NACOS_GROUP) \ +SEATA_REGISTRY_NACOS_CLUSTER=default \ +SEATA_REGISTRY_NACOS_CONTEXTPATH= \ +SEATA_REGISTRY_NACOS_USERNAME=$(NACOS_USERNAME) \ +SEATA_REGISTRY_NACOS_PASSWORD=$(NACOS_PASSWORD) \ +SEATA_REGISTRY_NACOS_ACCESSKEY= \ +SEATA_REGISTRY_NACOS_SECRETKEY= \ +SEATA_REGISTRY_NACOS_RAMROLENAME= \ +SEATA_STORE_TYPE=file +endef + +# Dynamically resolve the namingserver/server version from the Maven project (e.g. 2.8.0-SNAPSHOT) SERVER_VERSION ?= $(shell $(MVN) help:evaluate -Dexpression=project.version -q -DforceStdout) -NATIVE_PLATFORM=$(shell $(MVN) help:evaluate -Dexpression=native.platform -q -DforceStdout) +NATIVE_PLATFORM ?= $(shell $(MVN) help:evaluate -Dexpression=native.platform -q -DforceStdout) clean: ## Clean the project $(MVN) $(MAVEN_ARGS) clean spotless-check: ## Run Spotless code format check - $(MVN) $(MAVEN_ARGS) spotless:check -Ptest-native-metadata-merge -Ptest-native-namingserver + $(MVN) $(MAVEN_ARGS) spotless:check -Ptest-native-metadata-merge -Ptest-native-namingserver -Ptest-native-server spotless-apply: ## Apply Spotless code formatting $(MVN) $(MAVEN_ARGS) spotless:apply -Ptest-native-metadata-merge -Ptest-native-namingserver @@ -118,6 +166,32 @@ run-namingserver-native-jar: ## Run namingserver with GraalVM native-image agent @echo " make run-merge-native-namingserver" ${GRAALVM_HOME}/bin/java -agentlib:native-image-agent=config-output-dir=./target/native-image-config -jar ./namingserver/target/seata-namingserver.jar --console.user.username=seata --console.user.password=seata +install-run-server-native-file-jar: install-server-jar ## Build, install, and run server with GraalVM native-image agent + @$(MAKE) --no-print-directory run-server-native-file-jar + +run-server-native-file-jar: ## Run server with GraalVM native-image agent (without prior build/install) + @echo "=== Workload steps (run in separate terminals) ===" + @echo "1. Start server in seata registry mode connecting to server:" + @echo " make install-run-server-jar-registry-seata" + @echo " or" + @echo " make run-server-jar-registry-seata" + @echo "2. Run the native server test suite:" + @echo " make test-native-server" + @echo "3. After tests pass, stop this server (Ctrl+C) so the agent flushes metadata," + @echo " then merge the collected metadata:" + @echo " make run-merge-native-server" + SEATA_CONFIG_TYPE=file \ + SEATA_REGISTRY_TYPE=file \ + SEATA_STORE_TYPE=file \ + ${GRAALVM_HOME}/bin/java -agentlib:native-image-agent=config-output-dir=./target/native-image-config -jar ./server/target/seata-server.jar + +install-run-server-native-nacos-jar: install-server-jar ## Build, install, and run server with GraalVM native-image agent + @$(MAKE) --no-print-directory run-server-native-nacos-jar + +run-server-native-nacos-jar: ## Run server with GraalVM native-image agent (without prior build/install) + $(NACOS_MODE_ENV) \ + ${GRAALVM_HOME}/bin/java -agentlib:native-image-agent=config-output-dir=./target/native-image-config -jar ./server/target/seata-server.jar + install-run-server-jar: install-server-jar ## Build, install, and run the server JAR @$(MAKE) --no-print-directory run-server-jar @@ -137,10 +211,17 @@ run-server-jar-registry-seata: ## Run the server JAR (without prior build/instal test-native-namingserver: ## Run namingserver GraalVM native-image compatibility tests (requires GraalVM with native-image) $(MVN) $(MAVEN_ARGS) clean test -Ptest-native-namingserver -pl test-suite/test-native-namingserver +test-native-server: + $(MVN) $(MAVEN_ARGS) clean test -Ptest-native-server -pl test-suite/test-native-server + run-merge-native-namingserver: ## Merge collected native-image metadata into the namingserver resource directory (required to regenerate native metadata) EXECUTE_NATIVE_METADATA_MERGE_NAMINGSERVER=true \ $(MVN) $(MAVEN_ARGS) clean test -Dtest=ExecuteMergeNativeImageMetadataTests#namingServer -pl test-suite/test-native-metadata-merge -Ptest-native-metadata-merge +run-merge-native-server: ## Merge collected native-image metadata into the server resource directory (required to regenerate native metadata) + EXECUTE_NATIVE_METADATA_MERGE_SERVER=true \ + $(MVN) $(MAVEN_ARGS) clean test -Dtest=ExecuteMergeNativeImageMetadataTests#server -pl test-suite/test-native-metadata-merge -Ptest-native-metadata-merge + install-namingserver-native: install-namingserver-jar ## Build namingserver GraalVM native image (requires install-namingserver-jar including its spotless-apply dependency) @$(MAKE) --no-print-directory package-namingserver-native @@ -158,3 +239,33 @@ run-namingserver-native: ## Run the namingserver native image binary directly CONSOLE_USER_USERNAME=seata \ CONSOLE_USER_PASSWORD=seata \ ./namingserver/target/seata-namingserver-$(SERVER_VERSION)-$(NATIVE_PLATFORM) + +install-server-native: install-server-jar ## Build server GraalVM native image (requires install-server-jar including its spotless-apply dependency) + @$(MAKE) --no-print-directory package-server-native + +package-server-native: spotless-apply ## Build server GraalVM native image (requires install-server-native or install-server-jar to be executed first; spotless-apply runs first as a direct prerequisite) + $(MVN) $(MAVEN_ARGS) clean package -DskipTests -pl server spring-boot:process-aot -Pnative native:compile + +run-server-native-file: ## Run the server native image binary directly + @echo "=== Workload steps (run in separate terminals) ===" + @echo "1. Start server in seata registry mode connecting to server:" + @echo " make install-run-server-jar-registry-seata" + @echo " or" + @echo " make run-server-jar-registry-seata" + @echo "2. Run the native server test suite:" + @echo " make test-native-server" + SEATA_CONFIG_TYPE=file \ + SEATA_REGISTRY_TYPE=file \ + SEATA_STORE_TYPE=file \ + ./server/target/seata-server-$(SERVER_VERSION)-$(NATIVE_PLATFORM) + +run-server-native-nacos: ## Run the server native image binary directly + @echo "=== Workload steps (run in separate terminals) ===" + @echo "1. Start server in seata registry mode connecting to server:" + @echo " make install-run-server-jar-registry-seata" + @echo " or" + @echo " make run-server-jar-registry-seata" + @echo "2. Run the native server test suite:" + @echo " make test-native-server" + $(NACOS_MODE_ENV) \ + ./server/target/seata-server-$(SERVER_VERSION)-$(NATIVE_PLATFORM) diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md index f469799d64d..c7361e4ec60 100644 --- a/changes/en-us/2.x.md +++ b/changes/en-us/2.x.md @@ -21,6 +21,7 @@ Add changes here for all PR submitted to the 2.x branch. ### feature: - [[#8165](https://github.com/apache/incubator-seata/pull/8165)]/[[#8200](https://github.com/apache/incubator-seata/pull/8200)] add GraalVM native image build support for seata-namingserver +- [[#8162](https://github.com/apache/incubator-seata/pull/8162)] add GraalVM native image build support for seata-server - [[#8140](https://github.com/apache/incubator-seata/pull/8140)] support automatic updated marking after BusinessActionContext modifications - [[#8188](https://github.com/apache/incubator-seata/pull/8188)] support action status report and TccHook rollback interceptors in Saga annotation mode for anti-suspension and empty rollback diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md index abb4e5b94fd..cce5feadd3b 100644 --- a/changes/zh-cn/2.x.md +++ b/changes/zh-cn/2.x.md @@ -21,6 +21,7 @@ ### feature: - [[#8165](https://github.com/apache/incubator-seata/pull/8165)]/[[#8200](https://github.com/apache/incubator-seata/pull/8200)] 为 seata-namingserver 添加 GraalVM 原生镜像构建支持 +- [[#8162](https://github.com/apache/incubator-seata/pull/8162)] 为 seata-server 添加 GraalVM 原生镜像构建支持 - [[#8140](https://github.com/apache/incubator-seata/pull/8140)] 支持在 BusinessActionContext 变更后自动标记 updated - [[#8188](https://github.com/apache/incubator-seata/pull/8188)] Saga 注解模式支持 action status 上报和 TccHook 回滚切面,增强防悬挂和空回滚能力 diff --git a/dependencies/pom.xml b/dependencies/pom.xml index ab927918349..8202887ea48 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -83,7 +83,7 @@ 4.0.63 2.0.52 4.0.31 - 1.5.0-4 + 1.5.7-3 2.18.3 3.1.1 1.4.21 diff --git a/distribution/release-seata.xml b/distribution/release-seata.xml index 01ca07e7b25..e670c3bf810 100644 --- a/distribution/release-seata.xml +++ b/distribution/release-seata.xml @@ -165,9 +165,13 @@ seata-server/conf/ + - ../server/src/main/resources/logback-spring.xml + ../server/src/main/resources/logback-spring-jvm.xml seata-server/conf/ + logback-spring.xml diff --git a/pom.xml b/pom.xml index 42c0c5d3c29..5655ad71e7c 100644 --- a/pom.xml +++ b/pom.xml @@ -395,6 +395,12 @@ + + test-native-server + + test-suite/test-native-server + + test-native-namingserver diff --git a/server/pom.xml b/server/pom.xml index c9abdc9dcd8..6d0b04dca3a 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -479,6 +479,10 @@ + + org.graalvm.buildtools + native-maven-plugin + @@ -533,6 +537,7 @@ + release-seata-jar @@ -561,5 +566,128 @@ + + + native + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + + + + + + org.springframework.boot + spring-boot-maven-plugin + + org.apache.seata.server.ServerApplication + + + + process-aot + + process-aot + + + + + + org.graalvm.buildtools + native-maven-plugin + + org.apache.seata.server.ServerApplication + ${project.build.outputDirectory} + ${project.artifactId}-${project.version}-${native.platform} + + --initialize-at-build-time=ch.qos.logback.classic.Logger + --initialize-at-build-time=ch.qos.logback.classic.LoggerContext + --initialize-at-build-time=ch.qos.logback.classic.spi.TurboFilterList + --initialize-at-build-time=ch.qos.logback.classic.spi.LoggerContextVO + --initialize-at-build-time=ch.qos.logback.classic.Level + --initialize-at-build-time=ch.qos.logback.core.BasicStatusManager + --initialize-at-build-time=ch.qos.logback.core.spi.LogbackLock + --initialize-at-build-time=ch.qos.logback.core.helpers.CyclicBuffer + --initialize-at-build-time=ch.qos.logback.core.status.InfoStatus + --initialize-at-build-time=ch.qos.logback.classic.util.LogbackMDCAdapter + --initialize-at-build-time=ch.qos.logback.core.ConsoleAppender + --initialize-at-build-time=ch.qos.logback.core.spi.AppenderAttachableImpl + --initialize-at-build-time=ch.qos.logback.classic.util.ContextInitializer + --initialize-at-build-time=ch.qos.logback.core.util.COWArrayList + --initialize-at-build-time=ch.qos.logback.core.util.ReentryGuard + --initialize-at-build-time=ch.qos.logback.core.util.ReentryGuard$ReentryGuardImpl + --initialize-at-build-time=ch.qos.logback.core.util.SimpleTimeBasedGuard + --initialize-at-build-time=ch.qos.logback.core.spi.FilterAttachableImpl + --initialize-at-build-time=ch.qos.logback.core.joran.spi.ConsoleTarget + --initialize-at-build-time=ch.qos.logback.core.joran.spi.ConsoleTarget$1 + --initialize-at-build-time=ch.qos.logback.core.joran.spi.ConsoleTarget$2 + --initialize-at-build-time=ch.qos.logback.core.spi.ContextAwareImpl + --initialize-at-build-time=ch.qos.logback.classic.BasicConfigurator + --initialize-at-build-time=ch.qos.logback.core.encoder.LayoutWrappingEncoder + --initialize-at-build-time=ch.qos.logback.classic.layout.TTLLLayout + --initialize-at-build-time=ch.qos.logback.classic.pattern.ThrowableProxyConverter + --initialize-at-build-time=ch.qos.logback.core.util.CachingDateFormatter + --initialize-at-build-time=ch.qos.logback.core.util.CachingDateFormatter$CacheTuple + --initialize-at-build-time=ch.qos.logback.classic.util.ContextInitializer + --initialize-at-build-time=ch.qos.logback.classic.util.ContextInitializer$1 + --initialize-at-build-time=com.alibaba.fastjson2.reader.ObjectReaderBaseModule + --initialize-at-build-time=com.alibaba.fastjson2.reader.ObjectReaderBaseModule$ReaderAnnotationProcessor + --initialize-at-build-time=com.alibaba.fastjson2.util.TypeUtils + --initialize-at-build-time=com.alibaba.fastjson2.util.TypeUtils$Cache + --initialize-at-build-time=com.alibaba.fastjson2.JSONFactory + --initialize-at-build-time=com.alibaba.fastjson2.JSONFactory$CacheItem + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToDouble + --initialize-at-build-time=com.alibaba.fastjson2.writer.ObjectWriterBaseModule + --initialize-at-build-time=com.alibaba.fastjson2.writer.ObjectWriterBaseModule$WriterAnnotationProcessor + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.StringToAny + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToBigDecimal + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToBigInteger + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToBoolean + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToByte + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToDouble + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToFloat + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToInteger + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToLong + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToNumber + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToShort + --initialize-at-build-time=com.alibaba.fastjson2.function.impl.ToString + --initialize-at-build-time=com.alibaba.fastjson2.reader.ObjectReaderImplString + --initialize-at-build-time=com.alibaba.fastjson2.reader.ObjectReaderProvider + --initialize-at-build-time=com.alibaba.fastjson2.reader.ObjectReaderProvider$LRUAutoTypeCache + --initialize-at-build-time=com.alibaba.fastjson2.util.ParameterizedTypeImpl + --initialize-at-build-time=com.alibaba.fastjson2.JSONReader + --initialize-at-build-time=com.alibaba.fastjson2.JSONReader$Context + --initialize-at-build-time=com.alibaba.fastjson2.writer.ObjectWriterCreator + --initialize-at-build-time=com.alibaba.fastjson2.writer.ObjectWriterCreator$LambdaInfo + --initialize-at-build-time=com.alibaba.fastjson2.reader.ObjectReaderCreator$LambdaSetterInfo + --initialize-at-run-time=io.netty.channel.kqueue.Native + --initialize-at-run-time=io.netty.channel.kqueue.KQueueEventArray + + + + org.springframework.boot + spring-boot-devtools + + + + + + add-reachability-metadata + + add-reachability-metadata + + + + + + + + diff --git a/server/src/main/java/org/apache/seata/server/ApolloNativeRuntimeHints.java b/server/src/main/java/org/apache/seata/server/ApolloNativeRuntimeHints.java new file mode 100644 index 00000000000..988cb92082f --- /dev/null +++ b/server/src/main/java/org/apache/seata/server/ApolloNativeRuntimeHints.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.seata.server; + +import com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory; +import com.ctrip.framework.apollo.spring.property.PlaceholderHelper; +import com.ctrip.framework.apollo.spring.property.SpringValueRegistry; +import org.jspecify.annotations.NonNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; + +/** + * Registers reflection hints for Apollo Guice-managed classes that are not + * automatically detected by Spring AOT processing because they are instantiated + * via Guice instead of the Spring container. + */ +public class ApolloNativeRuntimeHints implements RuntimeHintsRegistrar { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApolloNativeRuntimeHints.class); + + private static final String[] APOLLO_GUICE_CLASSES = { + ConfigPropertySourceFactory.class.getName(), + PlaceholderHelper.class.getName(), + SpringValueRegistry.class.getName(), + }; + + @Override + public void registerHints(@NonNull RuntimeHints hints, ClassLoader classLoader) { + for (String className : APOLLO_GUICE_CLASSES) { + try { + Class clazz = Class.forName(className, false, classLoader); + hints.reflection() + .registerType( + clazz, + MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, + MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS, + MemberCategory.INVOKE_PUBLIC_METHODS, + MemberCategory.ACCESS_DECLARED_FIELDS); + } catch (ClassNotFoundException e) { + // Skip classes not available on the classpath + LOGGER.error("Apollo Guice class not found on classpath: {}", className, e); + } + } + } +} diff --git a/server/src/main/java/org/apache/seata/server/NacosPayloadRegistryInitializer.java b/server/src/main/java/org/apache/seata/server/NacosPayloadRegistryInitializer.java new file mode 100644 index 00000000000..afdcfab385b --- /dev/null +++ b/server/src/main/java/org/apache/seata/server/NacosPayloadRegistryInitializer.java @@ -0,0 +1,194 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.server; + +import com.alibaba.nacos.api.config.remote.request.*; +import com.alibaba.nacos.api.config.remote.response.*; +import com.alibaba.nacos.api.naming.remote.request.*; +import com.alibaba.nacos.api.naming.remote.response.*; +import com.alibaba.nacos.api.remote.request.*; +import com.alibaba.nacos.api.remote.response.*; +import org.jspecify.annotations.NonNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.Ordered; +import org.springframework.core.PriorityOrdered; + +import java.lang.reflect.Field; +import java.util.Map; + +/** + * Pre-populates the Nacos {@code PayloadRegistry} with all known + * {@code Request}/{@code Response} subclasses at application startup, + * before any Nacos client beans are created. + * + *

The Nacos client (version 2.0.4) uses the Reflections library to + * classpath-scan for {@code Payload} implementations in its + * {@code PayloadRegistry.scan()} static initializer. In a GraalVM native + * image, Reflections classpath scanning does not work, leaving the + * registry empty. This causes {@code Unknown payload type} errors when + * the Nacos gRPC client tries to parse server responses such as + * {@code ServerCheckResponse}. + * + *

This initializer implements {@link PriorityOrdered} and must run + * before any other initializer (e.g. {@code SeataPropertiesLoader}) that + * may trigger class loading of {@code StoreConfig}, whose static + * initializer instantiates the Nacos config client, which in turn + * triggers {@code PayloadRegistry.init()} via {@code RpcClient.}. + * + * @see com.alibaba.nacos.api.remote.PayloadRegistry + */ +public class NacosPayloadRegistryInitializer + implements ApplicationContextInitializer, PriorityOrdered { + + private static final Logger LOGGER = LoggerFactory.getLogger(NacosPayloadRegistryInitializer.class); + + /** + * Fully-qualified class name of the Nacos PayloadRegistry. + */ + private static final String PAYLOAD_REGISTRY_CLASS = "com.alibaba.nacos.api.remote.PayloadRegistry"; + + /** + * All known concrete {@code Request} subclasses in the + * nacos-client 2.0.x classpath. Abstract classes like + * {@code InternalRequest}, {@code ServerRequest}, + * {@code AbstractConfigRequest}, and {@code AbstractNamingRequest} + * are intentionally omitted — PayloadRegistry.register() skips + * them anyway. + */ + private static final String[] REQUEST_CLASSES = { + ClientConfigMetricRequest.class.getName(), + ConfigBatchListenRequest.class.getName(), + ConfigChangeNotifyRequest.class.getName(), + ConfigPublishRequest.class.getName(), + ConfigQueryRequest.class.getName(), + ConfigRemoveRequest.class.getName(), + InstanceRequest.class.getName(), + NotifySubscriberRequest.class.getName(), + ServiceListRequest.class.getName(), + ServiceQueryRequest.class.getName(), + SubscribeServiceRequest.class.getName(), + ClientDetectionRequest.class.getName(), + ConnectResetRequest.class.getName(), + ConnectionSetupRequest.class.getName(), + HealthCheckRequest.class.getName(), + PushAckRequest.class.getName(), + ServerCheckRequest.class.getName(), + ServerLoaderInfoRequest.class.getName(), + ServerReloadRequest.class.getName(), + }; + + /** + * All known concrete {@code Response} subclasses in the + * nacos-client 2.0.x classpath. + */ + private static final String[] RESPONSE_CLASSES = { + ClientConfigMetricResponse.class.getName(), + ConfigChangeBatchListenResponse.class.getName(), + ConfigChangeNotifyResponse.class.getName(), + ConfigPublishResponse.class.getName(), + ConfigQueryResponse.class.getName(), + ConfigRemoveResponse.class.getName(), + InstanceResponse.class.getName(), + NotifySubscriberResponse.class.getName(), + QueryServiceResponse.class.getName(), + ServiceListResponse.class.getName(), + SubscribeServiceResponse.class.getName(), + ClientDetectionResponse.class.getName(), + ConnectResetResponse.class.getName(), + ErrorResponse.class.getName(), + HealthCheckResponse.class.getName(), + ServerCheckResponse.class.getName(), + ServerLoaderInfoResponse.class.getName(), + ServerReloadResponse.class.getName(), + }; + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + + @Override + public void initialize(@NonNull ConfigurableApplicationContext applicationContext) { + try { + populatePayloadRegistry(); + } catch (Exception e) { + LOGGER.warn( + "Failed to pre-populate Nacos PayloadRegistry. " + + "Nacos gRPC communication may fail with " + + "'Unknown payload type' errors.", + e); + } + } + + private void populatePayloadRegistry() throws Exception { + Class payloadRegistryClass = Class.forName(PAYLOAD_REGISTRY_CLASS); + + // Access the private static REGISTRY_REQUEST map + Field registryField = payloadRegistryClass.getDeclaredField("REGISTRY_REQUEST"); + registryField.setAccessible(true); + @SuppressWarnings("unchecked") + Map> registryMap = (Map>) registryField.get(null); + + // Access the initialized flag so we can prevent the broken + // Reflections-based scan from running later + Field initializedField = payloadRegistryClass.getDeclaredField("initialized"); + initializedField.setAccessible(true); + + int count = 0; + + // Register all Request subclasses + for (String className : REQUEST_CLASSES) { + try { + Class clazz = Class.forName(className); + String simpleName = clazz.getSimpleName(); + if (!registryMap.containsKey(simpleName)) { + registryMap.put(simpleName, clazz); + count++; + } + } catch (ClassNotFoundException e) { + LOGGER.debug("Nacos request class not on classpath, skipping: {}", className); + } + } + + // Register all Response subclasses + for (String className : RESPONSE_CLASSES) { + try { + Class clazz = Class.forName(className); + String simpleName = clazz.getSimpleName(); + if (!registryMap.containsKey(simpleName)) { + registryMap.put(simpleName, clazz); + count++; + } + } catch (ClassNotFoundException e) { + LOGGER.debug("Nacos response class not on classpath, skipping: {}", className); + } + } + + // Mark as initialized to prevent the Reflections-based scan + // from running (and potentially failing or throwing duplicate + // key exceptions) + initializedField.setBoolean(null, true); + + LOGGER.info( + "Pre-populated Nacos PayloadRegistry with {} request/response types " + + "(Reflections classpath scanning unavailable in native image)", + count); + } +} diff --git a/server/src/main/java/org/apache/seata/server/SeataServerRuntimeHints.java b/server/src/main/java/org/apache/seata/server/SeataServerRuntimeHints.java new file mode 100644 index 00000000000..38946c532a5 --- /dev/null +++ b/server/src/main/java/org/apache/seata/server/SeataServerRuntimeHints.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.seata.server; + +import org.jspecify.annotations.NonNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aot.hint.MemberCategory; +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; + +/** + * Registers GraalVM native-image reflection hints for all Seata SPI + * implementation classes discovered via the EnhancedServiceLoader mechanism. + * + *

EnhancedServiceLoader reads class names from {@code META-INF/services/} + * and {@code META-INF/seata/} descriptor files, then instantiates them + * reflectively using {@code Class.getDeclaredConstructor()}. In native images, + * those constructors must be registered via reflection hints. + * + *

This registrar dynamically scans all SPI descriptor files on the build + * classpath during Spring AOT processing, so new SPI implementations are + * automatically covered without manual curation. + * + *

The source {@code reachability-metadata.json} entries for these same + * classes are overwritten during the native build by the GraalVM + * {@code add-reachability-metadata} goal; programmatic hints registered here + * are immune to that overwrite because they are compiled into AOT-generated + * source code rather than written into the reachability metadata JSON file. + */ +public class SeataServerRuntimeHints implements RuntimeHintsRegistrar { + + private static final Logger LOGGER = LoggerFactory.getLogger(SeataServerRuntimeHints.class); + + /** + * Pattern to discover all SPI descriptor files across the classpath. + * EnhancedServiceLoader reads from both locations. + * + * @see org.apache.seata.common.loader.EnhancedServiceLoader.InnerEnhancedServiceLoader#SERVICES_DIRECTORY + * @see org.apache.seata.common.loader.EnhancedServiceLoader.InnerEnhancedServiceLoader#SEATA_DIRECTORY + */ + private static final String SERVICES_PATTERN = "classpath*:META-INF/services/*"; + + private static final String SEATA_PATTERN = "classpath*:META-INF/seata/*"; + + @Override + public void registerHints(@NonNull RuntimeHints hints, ClassLoader classLoader) { + int count = 0; + count += registerFromPattern(hints, classLoader, SERVICES_PATTERN); + count += registerFromPattern(hints, classLoader, SEATA_PATTERN); + LOGGER.info("Registered native reflection hints for {} Seata SPI implementation classes", count); + } + + private int registerFromPattern(RuntimeHints hints, ClassLoader classLoader, String locationPattern) { + int count = 0; + try { + ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(classLoader); + Resource[] resources = resolver.getResources(locationPattern); + for (Resource resource : resources) { + count += processServiceFile(hints, classLoader, resource); + } + } catch (IOException e) { + LOGGER.warn("Failed to scan SPI resources for pattern: {}", locationPattern, e); + } + return count; + } + + private int processServiceFile(RuntimeHints hints, ClassLoader classLoader, Resource resource) { + int count = 0; + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8))) { + String line; + while ((line = reader.readLine()) != null) { + // Strip comments and trim per ServiceLoader spec (JAR 3.0 §3.1) + int commentIndex = line.indexOf('#'); + if (commentIndex >= 0) { + line = line.substring(0, commentIndex); + } + line = line.trim(); + if (line.isEmpty()) { + continue; + } + if (registerClassHints(hints, classLoader, line)) { + count++; + } + } + } catch (Exception e) { + LOGGER.debug("Failed to process SPI file: {}", resource.getFilename(), e); + } + return count; + } + + private boolean registerClassHints(RuntimeHints hints, ClassLoader classLoader, String className) { + try { + Class clazz = Class.forName(className, false, classLoader); + hints.reflection() + .registerType( + clazz, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, MemberCategory.INVOKE_PUBLIC_METHODS); + LOGGER.debug("Registered native reflection hints for SPI class: {}", className); + return true; + } catch (ClassNotFoundException | NoClassDefFoundError e) { + LOGGER.debug("SPI class not available on classpath, skipping: {}", className); + return false; + } + } +} diff --git a/server/src/main/java/org/apache/seata/server/config/ServerInstanceStrategyConfig.java b/server/src/main/java/org/apache/seata/server/config/ServerInstanceStrategyConfig.java index c4d963957a3..4ac2c085e81 100644 --- a/server/src/main/java/org/apache/seata/server/config/ServerInstanceStrategyConfig.java +++ b/server/src/main/java/org/apache/seata/server/config/ServerInstanceStrategyConfig.java @@ -17,10 +17,14 @@ package org.apache.seata.server.config; import org.apache.seata.common.util.StringUtils; +import org.apache.seata.server.instance.AbstractSeataInstanceStrategy; import org.apache.seata.server.instance.GeneralInstanceStrategy; import org.apache.seata.server.instance.RaftServerInstanceStrategy; import org.apache.seata.server.instance.SeataInstanceStrategy; +import org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryNamingServerProperties; +import org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryProperties; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.server.autoconfigure.ServerProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -31,10 +35,19 @@ public class ServerInstanceStrategyConfig { String sessionMode; @Bean - public SeataInstanceStrategy seataInstanceStrategy() { + public SeataInstanceStrategy seataInstanceStrategy( + RegistryProperties registryProperties, + RegistryNamingServerProperties registryNamingServerProperties, + ServerProperties serverProperties) { + AbstractSeataInstanceStrategy strategy; if (StringUtils.equalsIgnoreCase("raft", sessionMode)) { - return new RaftServerInstanceStrategy(); + strategy = new RaftServerInstanceStrategy(); + } else { + strategy = new GeneralInstanceStrategy(); } - return new GeneralInstanceStrategy(); + strategy.setRegistryProperties(registryProperties); + strategy.setRegistryNamingServerProperties(registryNamingServerProperties); + strategy.setServerProperties(serverProperties); + return strategy; } } diff --git a/server/src/main/java/org/apache/seata/server/instance/AbstractSeataInstanceStrategy.java b/server/src/main/java/org/apache/seata/server/instance/AbstractSeataInstanceStrategy.java index 48dc7ef50c0..3bee086055f 100644 --- a/server/src/main/java/org/apache/seata/server/instance/AbstractSeataInstanceStrategy.java +++ b/server/src/main/java/org/apache/seata/server/instance/AbstractSeataInstanceStrategy.java @@ -16,9 +16,7 @@ */ package org.apache.seata.server.instance; -import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; -import jakarta.annotation.Resource; import org.apache.seata.common.metadata.Instance; import org.apache.seata.common.thread.ThreadPoolExecutorFactory; import org.apache.seata.core.protocol.Version; @@ -28,8 +26,8 @@ import org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.web.server.autoconfigure.ServerProperties; -import org.springframework.context.ApplicationContext; import java.util.Arrays; import java.util.Optional; @@ -41,27 +39,32 @@ public abstract class AbstractSeataInstanceStrategy implements SeataInstanceStrategy { - @Resource protected RegistryProperties registryProperties; protected ServerProperties serverProperties; - @Resource - protected ApplicationContext applicationContext; - - @Resource protected RegistryNamingServerProperties registryNamingServerProperties; + @Autowired + public void setRegistryProperties(RegistryProperties registryProperties) { + this.registryProperties = registryProperties; + } + + @Autowired + public void setServerProperties(ServerProperties serverProperties) { + this.serverProperties = serverProperties; + } + + @Autowired + public void setRegistryNamingServerProperties(RegistryNamingServerProperties registryNamingServerProperties) { + this.registryNamingServerProperties = registryNamingServerProperties; + } + protected final Logger logger = LoggerFactory.getLogger(getClass()); protected static volatile ScheduledExecutorService EXECUTOR_SERVICE; protected AtomicBoolean init = new AtomicBoolean(false); - @PostConstruct - public void postConstruct() { - this.serverProperties = applicationContext.getBean(ServerProperties.class); - } - @Override public void init() { String types = registryProperties.getType(); diff --git a/server/src/main/resources/META-INF/native-image/reachability-metadata.json b/server/src/main/resources/META-INF/native-image/reachability-metadata.json new file mode 100644 index 00000000000..0c87fea856a --- /dev/null +++ b/server/src/main/resources/META-INF/native-image/reachability-metadata.json @@ -0,0 +1,4518 @@ +{ + "reflection" : [ { + "type" : "boolean" + }, { + "type" : "boolean[]" + }, { + "type" : "ch.qos.logback.classic.AsyncAppender", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setIncludeCallerData", + "parameterTypes" : [ "boolean" ] + } ] + }, { + "type" : "ch.qos.logback.classic.BasicConfigurator", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "ch.qos.logback.classic.Level", + "methods" : [ { + "name" : "valueOf", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "ch.qos.logback.classic.LoggerContext" + }, { + "type" : "ch.qos.logback.classic.boolex.StubEventEvaluator", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setExpression", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "ch.qos.logback.classic.encoder.PatternLayoutEncoder", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "ch.qos.logback.classic.filter.LevelFilter", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setLevel", + "parameterTypes" : [ "ch.qos.logback.classic.Level" ] + } ] + }, { + "type" : "ch.qos.logback.classic.spi.LogbackServiceProvider" + }, { + "type" : "ch.qos.logback.classic.util.DefaultJoranConfigurator", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "ch.qos.logback.core.AsyncAppenderBase", + "methods" : [ { + "name" : "setDiscardingThreshold", + "parameterTypes" : [ "int" ] + }, { + "name" : "setNeverBlock", + "parameterTypes" : [ "boolean" ] + }, { + "name" : "setQueueSize", + "parameterTypes" : [ "int" ] + } ] + }, { + "type" : "ch.qos.logback.core.ConsoleAppender", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "ch.qos.logback.core.FileAppender", + "methods" : [ { + "name" : "setAppend", + "parameterTypes" : [ "boolean" ] + } ] + }, { + "type" : "ch.qos.logback.core.OutputStreamAppender", + "methods" : [ { + "name" : "setEncoder", + "parameterTypes" : [ "ch.qos.logback.core.encoder.Encoder" ] + } ] + }, { + "type" : "ch.qos.logback.core.UnsynchronizedAppenderBase", + "methods" : [ { + "name" : "addFilter", + "parameterTypes" : [ "ch.qos.logback.core.filter.Filter" ] + } ] + }, { + "type" : "ch.qos.logback.core.boolex.EventEvaluator" + }, { + "type" : "ch.qos.logback.core.encoder.Encoder" + }, { + "type" : "ch.qos.logback.core.encoder.LayoutWrappingEncoder", + "methods" : [ { + "name" : "setCharset", + "parameterTypes" : [ "java.nio.charset.Charset" ] + }, { + "name" : "setParent", + "parameterTypes" : [ "ch.qos.logback.core.spi.ContextAware" ] + } ] + }, { + "type" : "ch.qos.logback.core.filter.AbstractMatcherFilter", + "methods" : [ { + "name" : "setOnMatch", + "parameterTypes" : [ "ch.qos.logback.core.spi.FilterReply" ] + }, { + "name" : "setOnMismatch", + "parameterTypes" : [ "ch.qos.logback.core.spi.FilterReply" ] + } ] + }, { + "type" : "ch.qos.logback.core.filter.EvaluatorFilter", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setEvaluator", + "parameterTypes" : [ "ch.qos.logback.core.boolex.EventEvaluator" ] + } ] + }, { + "type" : "ch.qos.logback.core.filter.Filter" + }, { + "type" : "ch.qos.logback.core.pattern.PatternLayoutEncoderBase", + "methods" : [ { + "name" : "setPattern", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "ch.qos.logback.core.rolling.RollingFileAppender", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setFile", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setRollingPolicy", + "parameterTypes" : [ "ch.qos.logback.core.rolling.RollingPolicy" ] + } ] + }, { + "type" : "ch.qos.logback.core.rolling.RollingPolicy" + }, { + "type" : "ch.qos.logback.core.rolling.RollingPolicyBase", + "methods" : [ { + "name" : "setFileNamePattern", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setParent", + "parameterTypes" : [ "ch.qos.logback.core.FileAppender" ] + } ] + }, { + "type" : "ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setMaxFileSize", + "parameterTypes" : [ "ch.qos.logback.core.util.FileSize" ] + } ] + }, { + "type" : "ch.qos.logback.core.rolling.TimeBasedRollingPolicy", + "methods" : [ { + "name" : "setCleanHistoryOnStart", + "parameterTypes" : [ "boolean" ] + }, { + "name" : "setMaxHistory", + "parameterTypes" : [ "int" ] + }, { + "name" : "setTotalSizeCap", + "parameterTypes" : [ "ch.qos.logback.core.util.FileSize" ] + } ] + }, { + "type" : "ch.qos.logback.core.spi.ContextAware" + }, { + "type" : "ch.qos.logback.core.spi.FilterReply" + }, { + "type" : "ch.qos.logback.core.util.FileSize", + "methods" : [ { + "name" : "valueOf", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "com.beust.jcommander.validators.NoValueValidator", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.ctrip.framework.apollo.spring.boot.ApolloApplicationContextInitializer", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory" + }, { + "type" : "com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory$$FastClassByGuice$$1266330", + "fields" : [ { + "name" : "GUICE$INVOKERS" + } ] + }, { + "type" : "com.ctrip.framework.apollo.spring.property.PlaceholderHelper" + }, { + "type" : "com.ctrip.framework.apollo.spring.property.PlaceholderHelper$$FastClassByGuice$$722328", + "fields" : [ { + "name" : "GUICE$INVOKERS" + } ] + }, { + "type" : "com.ctrip.framework.apollo.spring.property.SpringValueRegistry" + }, { + "type" : "com.ctrip.framework.apollo.spring.property.SpringValueRegistry$$FastClassByGuice$$2389604", + "fields" : [ { + "name" : "GUICE$INVOKERS" + } ] + }, { + "type" : "com.ctrip.framework.apollo.spring.util.SpringInjector$SpringModule" + }, { + "type" : "com.fasterxml.jackson.databind.deser.Deserializers[]" + }, { + "type" : "com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.google.common.eventbus.ElementTypesAreNonnullByDefault" + }, { + "type" : "com.google.common.eventbus.Subscribe" + }, { + "type" : "com.google.common.util.concurrent.AbstractFuture", + "fields" : [ { + "name" : "listeners" + }, { + "name" : "value" + }, { + "name" : "waiters" + } ] + }, { + "type" : "com.google.common.util.concurrent.AbstractFuture$Waiter", + "fields" : [ { + "name" : "next" + }, { + "name" : "thread" + } ] + }, { + "type" : "com.google.inject.AbstractModule" + }, { + "type" : "com.google.inject.internal.Annotations" + }, { + "type" : "com.google.inject.internal.InjectorShell$RootModule" + }, { + "type" : "com.google.inject.kotlin.KotlinSupportImpl" + }, { + "type" : "com.google.inject.util.Modules$EmptyModule" + }, { + "type" : "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "groovy.lang.MetaClass" + }, { + "type" : "int[]" + }, { + "type" : "io.netty.bootstrap.ServerBootstrap$1" + }, { + "type" : "io.netty.bootstrap.ServerBootstrap$ServerBootstrapAcceptor" + }, { + "type" : "io.netty.buffer.AbstractByteBufAllocator" + }, { + "type" : "io.netty.buffer.AdaptivePoolingAllocator$Magazine" + }, { + "type" : "io.netty.buffer.AdaptivePoolingAllocator$SizeClassedChunk" + }, { + "type" : "io.netty.channel.AbstractChannelHandlerContext" + }, { + "type" : "io.netty.channel.ChannelHandler$Sharable" + }, { + "type" : "io.netty.channel.ChannelOutboundBuffer" + }, { + "type" : "io.netty.channel.DefaultChannelConfig" + }, { + "type" : "io.netty.channel.DefaultChannelPipeline" + }, { + "type" : "io.netty.channel.DefaultChannelPipeline$HeadContext" + }, { + "type" : "io.netty.channel.DefaultChannelPipeline$TailContext" + }, { + "type" : "io.netty.channel.socket.nio.NioServerSocketChannel", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "io.netty.handler.timeout.IdleStateHandler" + }, { + "type" : "io.netty.util.DefaultAttributeMap" + }, { + "type" : "io.netty.util.Recycler$DefaultHandle" + }, { + "type" : "io.netty.util.ReferenceCountUtil" + }, { + "type" : "io.netty.util.ResourceLeakDetector$DefaultResourceLeak" + }, { + "type" : "io.netty.util.concurrent.ConcurrentSkipListIntObjMultimap" + }, { + "type" : "io.netty.util.concurrent.ConcurrentSkipListIntObjMultimap$Index" + }, { + "type" : "io.netty.util.concurrent.ConcurrentSkipListIntObjMultimap$Node" + }, { + "type" : "io.netty.util.concurrent.DefaultPromise" + }, { + "type" : "io.netty.util.concurrent.MpscIntQueue$MpscAtomicIntegerArrayQueue" + }, { + "type" : "io.netty.util.concurrent.SingleThreadEventExecutor" + }, { + "type" : "io.netty.util.internal.CleanerJava25$CleanableDirectBufferImpl", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.AutoCloseable", "java.nio.ByteBuffer", "long" ] + } ] + }, { + "type" : "io.netty.util.internal.shaded.org.jctools.queues.atomic.BaseMpscLinkedAtomicArrayQueueColdProducerFields" + }, { + "type" : "io.netty.util.internal.shaded.org.jctools.queues.atomic.BaseMpscLinkedAtomicArrayQueueConsumerFields" + }, { + "type" : "io.netty.util.internal.shaded.org.jctools.queues.atomic.BaseMpscLinkedAtomicArrayQueueProducerFields" + }, { + "type" : "io.netty.util.internal.shaded.org.jctools.queues.atomic.MpmcAtomicArrayQueueConsumerIndexField" + }, { + "type" : "io.netty.util.internal.shaded.org.jctools.queues.atomic.MpmcAtomicArrayQueueProducerIndexField" + }, { + "type" : "io.seata.common.thread.ThreadPoolProvider" + }, { + "type" : "io.seata.config.ExtConfigurationProvider" + }, { + "type" : "io.seata.config.file.FileConfig" + }, { + "type" : "io.seata.core.context.ContextCore" + }, { + "type" : "io.seata.core.rpc.RegisterCheckAuthHandler" + }, { + "type" : "io.seata.core.rpc.hook.RpcHook" + }, { + "type" : "io.seata.core.rpc.netty.http.filter.HttpRequestFilter" + }, { + "type" : "io.seata.core.serializer.Serializer" + }, { + "type" : "io.seata.discovery.registry.RegistryProvider" + }, { + "type" : "io.seata.metrics.exporter.Exporter" + }, { + "type" : "io.seata.metrics.registry.Registry" + }, { + "type" : "io.seata.server.coordinator.AbstractCore" + }, { + "type" : "io.seata.server.limit.ratelimit.RateLimiter" + }, { + "type" : "io.seata.server.lock.LockManager" + }, { + "type" : "io.seata.server.session.SessionManager" + }, { + "type" : "io.seata.server.store.VGroupMappingStoreManager" + }, { + "type" : "jakarta.annotation.Nullable" + }, { + "type" : "jakarta.annotation.PostConstruct" + }, { + "type" : "jakarta.annotation.PreDestroy" + }, { + "type" : "jakarta.annotation.Resource" + }, { + "type" : "jakarta.ejb.Asynchronous" + }, { + "type" : "jakarta.ejb.EJB" + }, { + "type" : "jakarta.enterprise.concurrent.Asynchronous" + }, { + "type" : "jakarta.inject.Inject" + }, { + "type" : "jakarta.inject.Named" + }, { + "type" : "jakarta.inject.Provider" + }, { + "type" : "jakarta.inject.Qualifier" + }, { + "type" : "jakarta.persistence.EntityManagerFactory" + }, { + "type" : "jakarta.servlet.Servlet" + }, { + "type" : "jakarta.validation.Validator" + }, { + "type" : "java.io.Closeable" + }, { + "type" : "java.io.Console", + "methods" : [ { + "name" : "isTerminal", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.io.Serializable" + }, { + "type" : "java.io.Serializable[]" + }, { + "type" : "java.lang.AutoCloseable" + }, { + "type" : "java.lang.Boolean", + "jniAccessible" : true, + "methods" : [ { + "name" : "getBoolean", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "java.lang.Byte" + }, { + "type" : "java.lang.CharSequence[]" + }, { + "type" : "java.lang.Class", + "methods" : [ { + "name" : "getModule", + "parameterTypes" : [ ] + }, { + "name" : "isRecord", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.ClassLoader", + "fields" : [ { + "name" : "classLoaderValueMap" + } ] + }, { + "type" : "java.lang.Class[]" + }, { + "type" : "java.lang.CloneNotSupportedException" + }, { + "type" : "java.lang.Comparable[]" + }, { + "type" : "java.lang.Double" + }, { + "type" : "java.lang.Error" + }, { + "type" : "java.lang.Float" + }, { + "type" : "java.lang.Integer" + }, { + "type" : "java.lang.Long" + }, { + "type" : "java.lang.Module", + "methods" : [ { + "name" : "isNativeAccessEnabled", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.Object", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.Object[]" + }, { + "type" : "java.lang.ProcessHandle", + "methods" : [ { + "name" : "current", + "parameterTypes" : [ ] + }, { + "name" : "pid", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.RuntimeException", + "jniAccessible" : true + }, { + "type" : "java.lang.Short" + }, { + "type" : "java.lang.String", + "methods" : [ { + "name" : "equals", + "parameterTypes" : [ "java.lang.Object" ] + } ] + }, { + "type" : "java.lang.String[]" + }, { + "type" : "java.lang.Thread", + "methods" : [ { + "name" : "isVirtual", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.Throwable" + }, { + "type" : "java.lang.annotation.Documented" + }, { + "type" : "java.lang.annotation.Inherited" + }, { + "type" : "java.lang.annotation.Repeatable" + }, { + "type" : "java.lang.annotation.Retention" + }, { + "type" : "java.lang.annotation.Target" + }, { + "type" : "java.lang.constant.Constable[]" + }, { + "type" : "java.lang.constant.ConstantDesc[]" + }, { + "type" : "java.lang.foreign.Arena", + "methods" : [ { + "name" : "allocate", + "parameterTypes" : [ "long" ] + }, { + "name" : "ofShared", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.foreign.MemorySegment", + "methods" : [ { + "name" : "address", + "parameterTypes" : [ ] + }, { + "name" : "asByteBuffer", + "parameterTypes" : [ ] + }, { + "name" : "ofBuffer", + "parameterTypes" : [ "java.nio.Buffer" ] + }, { + "name" : "ofAddress", + "parameterTypes" : [ "long" ] + }, { + "name" : "reinterpret", + "parameterTypes" : [ "long" ] + } ] + }, { + "type" : "java.lang.invoke.MethodHandles", + "methods" : [ { + "name" : "byteArrayViewVarHandle", + "parameterTypes" : [ "java.lang.Class", "java.nio.ByteOrder" ] + }, { + "name" : "byteBufferViewVarHandle", + "parameterTypes" : [ "java.lang.Class", "java.nio.ByteOrder" ] + }, { + "name" : "privateLookupIn", + "parameterTypes" : [ "java.lang.Class", "java.lang.invoke.MethodHandles$Lookup" ] + } ] + }, { + "type" : "java.lang.invoke.MethodHandles$Lookup", + "methods" : [ { + "name" : "findVarHandle", + "parameterTypes" : [ "java.lang.Class", "java.lang.String", "java.lang.Class" ] + } ] + }, { + "type" : "java.lang.invoke.VarHandle", + "methods" : [ { + "name" : "acquireFence", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.management.ManagementFactory", + "methods" : [ { + "name" : "getRuntimeMXBean", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.management.RuntimeMXBean", + "methods" : [ { + "name" : "getInputArguments", + "parameterTypes" : [ ] + }, { + "name" : "getName", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.reflect.ParameterizedType", + "methods" : [ { + "name" : "getActualTypeArguments", + "parameterTypes" : [ ] + }, { + "name" : "getRawType", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.reflect.UndeclaredThrowableException" + }, { + "type" : "java.lang.reflect.WildcardType", + "methods" : [ { + "name" : "getUpperBounds", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.nio.ByteBuffer", + "methods" : [ { + "name" : "alignedSlice", + "parameterTypes" : [ "int" ] + }, { + "name" : "put", + "parameterTypes" : [ "int", "java.nio.ByteBuffer", "int", "int" ] + }, { + "name" : "put", + "parameterTypes" : [ "int", "byte[]", "int", "int" ] + }, { + "name" : "slice", + "parameterTypes" : [ "int", "int" ] + } ] + }, { + "type" : "java.nio.channels.spi.SelectorProvider" + }, { + "type" : "java.nio.charset.Charset" + }, { + "type" : "java.sql.Date" + }, { + "type" : "java.sql.Timestamp" + }, { + "type" : "java.util.EventListener" + }, { + "type" : "java.util.concurrent.Executor" + }, { + "type" : "java.util.concurrent.ThreadFactory" + }, { + "type" : "java.util.logging.LogManager" + }, { + "type" : "javax.annotation.Nonnull" + }, { + "type" : "javax.annotation.Nullable" + }, { + "type" : "javax.annotation.meta.TypeQualifier" + }, { + "type" : "javax.annotation.meta.TypeQualifierDefault" + }, { + "type" : "javax.money.MonetaryAmount" + }, { + "type" : "javax.naming.InitialContext" + }, { + "type" : "jdk.crac.management.CRaCMXBean" + }, { + "type" : "jdk.internal.loader.ClassLoaders$AppClassLoader" + }, { + "type" : "jdk.internal.loader.ClassLoaders$PlatformClassLoader" + }, { + "type" : "jdk.internal.misc.Unsafe", + "methods" : [ { + "name" : "getUnsafe", + "parameterTypes" : [ ] + } ] + }, { + "type" : "kotlin.Metadata" + }, { + "type" : "kotlin.coroutines.Continuation" + }, { + "type" : "kotlin.jvm.JvmInline" + }, { + "type" : "kotlin.reflect.full.KClasses" + }, { + "type" : "kotlinx.coroutines.reactor.MonoKt" + }, { + "type" : "kotlinx.serialization.Serializable" + }, { + "type" : "long[]" + }, { + "type" : "org.apache.commons.logging.LogFactory" + }, { + "type" : "org.apache.commons.logging.impl.Slf4jLogFactory", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.commons.logging.impl.WeakHashtable", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.logging.log4j.core.impl.Log4jContextFactory" + }, { + "type" : "org.apache.logging.log4j.util.EnvironmentPropertySource" + }, { + "type" : "org.apache.logging.log4j.util.SystemPropertiesPropertySource" + }, { + "type" : "org.apache.logging.slf4j.SLF4JProvider" + }, { + "type" : "org.apache.seata.common.loader.LoadLevel" + }, { + "type" : "org.apache.seata.common.loader.Scope" + }, { + "type" : "org.apache.seata.common.store.LockMode", + "methods" : [ { + "name" : "getName", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.common.store.SessionMode", + "methods" : [ { + "name" : "getName", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.common.thread.PlatformThreadPoolProvider", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.common.thread.VirtualThreadPoolProvider", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.config.Configuration", + "methods" : [ { + "name" : "addConfigListener", + "parameterTypes" : [ "java.lang.String", "org.apache.seata.config.ConfigurationChangeListener" ] + }, { + "name" : "getBoolean", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "getBoolean", + "parameterTypes" : [ "java.lang.String", "boolean" ] + }, { + "name" : "getConfig", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "getConfig", + "parameterTypes" : [ "java.lang.String", "java.lang.String" ] + }, { + "name" : "getInt", + "parameterTypes" : [ "java.lang.String", "int" ] + }, { + "name" : "getLatestConfig", + "parameterTypes" : [ "java.lang.String", "java.lang.String", "long" ] + }, { + "name" : "getLong", + "parameterTypes" : [ "java.lang.String", "long" ] + }, { + "name" : "getShort", + "parameterTypes" : [ "java.lang.String", "short" ] + } ] + }, { + "type" : "org.apache.seata.config.file.SimpleFileConfig", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.config.file.YamlFileConfig" + }, { + "type" : "org.apache.seata.core.context.FastThreadLocalContextCore", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.core.context.ThreadLocalContextCore" + }, { + "type" : "org.apache.seata.core.rpc.hook.StatusRpcHook", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.core.rpc.netty.AbstractNettyRemotingServer$ServerHandler" + }, { + "type" : "org.apache.seata.core.rpc.netty.MultiProtocolDecoder" + }, { + "type" : "org.apache.seata.core.rpc.netty.NettyServerBootstrap$1" + }, { + "type" : "org.apache.seata.core.rpc.netty.ProtocolDetectHandler" + }, { + "type" : "org.apache.seata.core.rpc.netty.http.filter.HttpRequestFilter" + }, { + "type" : "org.apache.seata.core.rpc.netty.v2.ProtocolDecoderV2" + }, { + "type" : "org.apache.seata.core.rpc.netty.v2.ProtocolEncoderV2" + }, { + "type" : "org.apache.seata.discovery.registry.FileRegistryProvider", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.discovery.registry.consul.ConsulRegistryProvider" + }, { + "type" : "org.apache.seata.discovery.registry.custom.CustomRegistryProvider" + }, { + "type" : "org.apache.seata.discovery.registry.etcd3.EtcdRegistryProvider" + }, { + "type" : "org.apache.seata.discovery.registry.eureka.EurekaRegistryProvider" + }, { + "type" : "org.apache.seata.discovery.registry.nacos.NacosRegistryProvider", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.discovery.registry.namingserver.NamingserverRegistryProvider", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.discovery.registry.redis.RedisRegistryProvider" + }, { + "type" : "org.apache.seata.discovery.registry.sofa.SofaRegistryProvider" + }, { + "type" : "org.apache.seata.discovery.registry.zk.ZookeeperRegistryProvider" + }, { + "type" : "org.apache.seata.metrics.exporter.prometheus.PrometheusExporter", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.metrics.registry.compact.CompactRegistry", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.serializer.fastjson2.Fastjson2Serializer" + }, { + "type" : "org.apache.seata.serializer.fory.ForySerializer" + }, { + "type" : "org.apache.seata.serializer.hessian.HessianSerializer" + }, { + "type" : "org.apache.seata.serializer.kryo.KryoSerializer" + }, { + "type" : "org.apache.seata.serializer.protobuf.GrpcSerializer" + }, { + "type" : "org.apache.seata.serializer.protobuf.ProtobufSerializer" + }, { + "type" : "org.apache.seata.serializer.seata.SeataSerializer", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Byte" ] + } ] + }, { + "type" : "org.apache.seata.server.ParameterParser", + "fields" : [ { + "name" : "help" + }, { + "name" : "host" + }, { + "name" : "lockStoreMode" + }, { + "name" : "port" + }, { + "name" : "seataEnv" + }, { + "name" : "serverNode" + }, { + "name" : "sessionStoreMode" + }, { + "name" : "storeMode" + } ] + }, { + "type" : "org.apache.seata.server.Server", + "fields" : [ { + "name" : "seataInstanceStrategy" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.ServerApplication", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "main", + "parameterTypes" : [ "java.lang.String[]" ] + } ] + }, { + "type" : "org.apache.seata.server.ServerRunner", + "fields" : [ { + "name" : "logPath" + }, { + "name" : "seataServer" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.auth.DefaultCheckAuthHandler", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.cluster.listener.ClusterChangeListener" + }, { + "type" : "org.apache.seata.server.cluster.manager.ClusterWatcherManager", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "init", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.cluster.manager.ClusterWatcherManager$$SpringCGLIB$$0", + "fields" : [ { + "name" : "CGLIB$CALLBACK_FILTER" + }, { + "name" : "CGLIB$FACTORY_DATA" + } ] + }, { + "type" : "org.apache.seata.server.cluster.raft.serializer.JacksonSerializer" + }, { + "type" : "org.apache.seata.server.config.AsyncConfig" + }, { + "type" : "org.apache.seata.server.config.AsyncConfig$$SpringCGLIB$$0", + "fields" : [ { + "name" : "$$beanFactory" + }, { + "name" : "CGLIB$CALLBACK_FILTER" + }, { + "name" : "CGLIB$FACTORY_DATA" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "CGLIB$SET_STATIC_CALLBACKS", + "parameterTypes" : [ "org.springframework.cglib.proxy.Callback[]" ] + } ] + }, { + "type" : "org.apache.seata.server.config.ServerConfig", + "methods" : [ { + "name" : "emptyServerProperties", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.config.ServerConfig$$SpringCGLIB$$0", + "fields" : [ { + "name" : "$$beanFactory" + }, { + "name" : "CGLIB$CALLBACK_FILTER" + }, { + "name" : "CGLIB$FACTORY_DATA" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "CGLIB$SET_STATIC_CALLBACKS", + "parameterTypes" : [ "org.springframework.cglib.proxy.Callback[]" ] + } ] + }, { + "type" : "org.apache.seata.server.config.ServerConfig$$SpringCGLIB$$FastClass$$0", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Class" ] + } ] + }, { + "type" : "org.apache.seata.server.config.ServerConfig$$SpringCGLIB$$FastClass$$1", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Class" ] + } ] + }, { + "type" : "org.apache.seata.server.config.ServerInstanceStrategyConfig", + "fields" : [ { + "name" : "sessionMode" + } ], + "methods" : [ { + "name" : "seataInstanceStrategy", + "parameterTypes" : [ "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryProperties", "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryNamingServerProperties", "org.springframework.boot.web.server.autoconfigure.ServerProperties" ] + } ] + }, { + "type" : "org.apache.seata.server.config.ServerInstanceStrategyConfig$$SpringCGLIB$$0", + "fields" : [ { + "name" : "$$beanFactory" + }, { + "name" : "CGLIB$CALLBACK_FILTER" + }, { + "name" : "CGLIB$FACTORY_DATA" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "CGLIB$SET_STATIC_CALLBACKS", + "parameterTypes" : [ "org.springframework.cglib.proxy.Callback[]" ] + } ] + }, { + "type" : "org.apache.seata.server.config.ServerInstanceStrategyConfig$$SpringCGLIB$$FastClass$$0", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Class" ] + } ] + }, { + "type" : "org.apache.seata.server.config.ServerInstanceStrategyConfig$$SpringCGLIB$$FastClass$$1", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Class" ] + } ] + }, { + "type" : "org.apache.seata.server.console.aop.GlobalExceptionHandlerAdvice", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.console.controller.BranchSessionController", + "fields" : [ { + "name" : "branchSessionService" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.console.controller.GlobalLockController", + "fields" : [ { + "name" : "globalLockService" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.console.controller.GlobalSessionController", + "fields" : [ { + "name" : "globalSessionService" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.console.impl.AbstractBranchService" + }, { + "type" : "org.apache.seata.server.console.impl.AbstractGlobalService" + }, { + "type" : "org.apache.seata.server.console.impl.AbstractLockService" + }, { + "type" : "org.apache.seata.server.console.impl.AbstractService" + }, { + "type" : "org.apache.seata.server.console.impl.file.BranchSessionFileServiceImpl" + }, { + "type" : "org.apache.seata.server.console.impl.file.BranchSessionFileServiceImpl$$SpringCGLIB$$0", + "fields" : [ { + "name" : "$$beanFactory" + }, { + "name" : "CGLIB$CALLBACK_FILTER" + }, { + "name" : "CGLIB$FACTORY_DATA" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "CGLIB$SET_STATIC_CALLBACKS", + "parameterTypes" : [ "org.springframework.cglib.proxy.Callback[]" ] + } ] + }, { + "type" : "org.apache.seata.server.console.impl.file.GlobalLockFileServiceImpl" + }, { + "type" : "org.apache.seata.server.console.impl.file.GlobalLockFileServiceImpl$$SpringCGLIB$$0", + "fields" : [ { + "name" : "$$beanFactory" + }, { + "name" : "CGLIB$CALLBACK_FILTER" + }, { + "name" : "CGLIB$FACTORY_DATA" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "CGLIB$SET_STATIC_CALLBACKS", + "parameterTypes" : [ "org.springframework.cglib.proxy.Callback[]" ] + } ] + }, { + "type" : "org.apache.seata.server.console.impl.file.GlobalSessionFileServiceImpl" + }, { + "type" : "org.apache.seata.server.console.impl.file.GlobalSessionFileServiceImpl$$SpringCGLIB$$0", + "fields" : [ { + "name" : "$$beanFactory" + }, { + "name" : "CGLIB$CALLBACK_FILTER" + }, { + "name" : "CGLIB$FACTORY_DATA" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "CGLIB$SET_STATIC_CALLBACKS", + "parameterTypes" : [ "org.springframework.cglib.proxy.Callback[]" ] + } ] + }, { + "type" : "org.apache.seata.server.console.service.BranchSessionService" + }, { + "type" : "org.apache.seata.server.console.service.GlobalLockService" + }, { + "type" : "org.apache.seata.server.console.service.GlobalSessionService" + }, { + "type" : "org.apache.seata.server.controller.ClusterController", + "fields" : [ { + "name" : "clusterWatcherManager" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.controller.HealthController", + "fields" : [ { + "name" : "serverRunner" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "healthCheck", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.controller.VGroupMappingController", + "fields" : [ { + "name" : "sessionMode" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.filter.RaftRequestFilter", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.filter.XSSHttpRequestFilter", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.instance.AbstractSeataInstanceStrategy", + "methods" : [ { + "name" : "destroy", + "parameterTypes" : [ ] + }, { + "name" : "setRegistryNamingServerProperties", + "parameterTypes" : [ "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryNamingServerProperties" ] + }, { + "name" : "setRegistryProperties", + "parameterTypes" : [ "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryProperties" ] + }, { + "name" : "setServerProperties", + "parameterTypes" : [ "org.springframework.boot.web.server.autoconfigure.ServerProperties" ] + } ] + }, { + "type" : "org.apache.seata.server.instance.GeneralInstanceStrategy" + }, { + "type" : "org.apache.seata.server.instance.SeataInstanceStrategy" + }, { + "type" : "org.apache.seata.server.limit.ratelimit.TokenBucketLimiter", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.logging.listener.SystemPropertyLoggerContextListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.logging.logback.ExtendedArrowThrowableProxyConverter", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.metrics.MetricsSubscriber", + "methods" : [ { + "name" : "recordGlobalTransactionEventForMetrics", + "parameterTypes" : [ "org.apache.seata.core.event.GlobalTransactionEvent" ] + } ] + }, { + "type" : "org.apache.seata.server.spring.listener.HttpFilterInitListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.spring.listener.ServerApplicationListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.storage.db.lock.DataBaseLockManager" + }, { + "type" : "org.apache.seata.server.storage.db.session.DataBaseSessionManager" + }, { + "type" : "org.apache.seata.server.storage.db.store.DataBaseVGroupMappingStoreManager" + }, { + "type" : "org.apache.seata.server.storage.file.lock.FileLockManager", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.storage.file.session.FileSessionManager", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.String", "java.lang.String" ] + } ] + }, { + "type" : "org.apache.seata.server.storage.file.store.FileVGroupMappingStoreManager", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "org.apache.seata.server.storage.raft.lock.RaftLockManager" + }, { + "type" : "org.apache.seata.server.storage.raft.session.RaftSessionManager" + }, { + "type" : "org.apache.seata.server.storage.raft.store.RaftVGroupMappingStoreManager" + }, { + "type" : "org.apache.seata.server.storage.redis.lock.RedisLockManager" + }, { + "type" : "org.apache.seata.server.storage.redis.session.RedisSessionManager" + }, { + "type" : "org.apache.seata.server.storage.redis.store.RedisVGroupMappingStoreManager" + }, { + "type" : "org.apache.seata.server.store.StoreConfig", + "methods" : [ { + "name" : "getLockMode", + "parameterTypes" : [ ] + }, { + "name" : "getSessionMode", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.transaction.at.ATCore", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.apache.seata.core.rpc.RemotingServer" ] + } ] + }, { + "type" : "org.apache.seata.server.transaction.saga.SagaAnnotationCore", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.apache.seata.core.rpc.RemotingServer" ] + } ] + }, { + "type" : "org.apache.seata.server.transaction.saga.SagaCore", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.apache.seata.core.rpc.RemotingServer" ] + } ] + }, { + "type" : "org.apache.seata.server.transaction.tcc.TccCore", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.apache.seata.core.rpc.RemotingServer" ] + } ] + }, { + "type" : "org.apache.seata.server.transaction.xa.XACore", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.apache.seata.core.rpc.RemotingServer" ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.SeataCoreAutoConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "springApplicationContextProvider", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.SeataCoreEnvironmentPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.SeataServerEnvironmentPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.http.RestControllerBeanPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.loader.SeataPropertiesLoader", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.LogProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.ShutdownProperties", + "fields" : [ { + "name" : "wait" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.ThreadFactoryProperties", + "fields" : [ { + "name" : "bossThreadPrefix" + }, { + "name" : "bossThreadSize" + }, { + "name" : "shareBossWorker" + }, { + "name" : "workerThreadPrefix" + }, { + "name" : "workerThreadSize" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.TransportProperties", + "fields" : [ { + "name" : "compressor" + }, { + "name" : "enableClientBatchSendRequest" + }, { + "name" : "enableTcServerBatchSendResponse" + }, { + "name" : "heartbeat" + }, { + "name" : "httpPoolKeepAliveTime" + }, { + "name" : "keepAliveTime" + }, { + "name" : "maxHttpPoolSize" + }, { + "name" : "maxHttpTaskQueueSize" + }, { + "name" : "maxServerPoolSize" + }, { + "name" : "maxTaskQueueSize" + }, { + "name" : "minHttpPoolSize" + }, { + "name" : "minServerPoolSize" + }, { + "name" : "rpcRmRequestTimeout" + }, { + "name" : "rpcTcRequestTimeout" + }, { + "name" : "rpcTmRequestTimeout" + }, { + "name" : "serialization" + }, { + "name" : "serverChannelMaxIdleTimeSeconds" + }, { + "name" : "serverSocketResvBufSize" + }, { + "name" : "serverSocketSendBufSize" + }, { + "name" : "soBackLogSize" + }, { + "name" : "threadpool" + }, { + "name" : "writeBufferHighWaterMark" + }, { + "name" : "writeBufferLowWaterMark" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.config.ConfigApolloProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.config.ConfigConsulProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.config.ConfigCustomProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.config.ConfigEtcd3Properties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.config.ConfigFileProperties", + "fields" : [ { + "name" : "name" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.config.ConfigNacosProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setAccessKey", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setContextPath", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setDataId", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setGroup", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setNamespace", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setPassword", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setRamRoleName", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setSecretKey", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setServerAddr", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setUsername", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.config.ConfigProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setType", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.config.ConfigZooKeeperProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryConsulProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryCustomProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryEtcd3Properties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryEurekaProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryMetadataProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryNacosProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setAccessKey", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setApplication", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setCluster", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setContextPath", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setGroup", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setNamespace", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setPassword", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setRamRoleName", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setSecretKey", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setServerAddr", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setUsername", + "parameterTypes" : [ "java.lang.String" ] + } ], + "fields" : [ { + "name" : "slbPattern" + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryNamingServerProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setCluster", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setHeartbeatPeriod", + "parameterTypes" : [ "int" ] + }, { + "name" : "setMetadataMaxAgeMs", + "parameterTypes" : [ "java.lang.Long" ] + }, { + "name" : "setNamespace", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setPassword", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setServerAddr", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setTokenValidityInMilliseconds", + "parameterTypes" : [ "java.lang.Long" ] + }, { + "name" : "setUsername", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryProperties", + "fields" : [ { + "name" : "ignoredInterfaces" + }, { + "name" : "preferredNetworks" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setType", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setIgnoredInterfaces", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setPreferredNetworks", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryRaftProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryRedisProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistrySofaProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryZooKeeperProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.MetricsProperties", + "fields" : [ { + "name" : "enabled" + }, { + "name" : "exporterList" + }, { + "name" : "exporterPrometheusPort" + }, { + "name" : "registryType" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.ServerProperties", + "fields" : [ { + "name" : "applicationDataLimit" + }, { + "name" : "applicationDataLimitCheck" + }, { + "name" : "enableCheckAuth" + }, { + "name" : "enableParallelHandleBranch" + }, { + "name" : "enableParallelRequestHandle" + }, { + "name" : "maxCommitRetryTimeout" + }, { + "name" : "maxRollbackRetryTimeout" + }, { + "name" : "retryDeadThreshold" + }, { + "name" : "rollbackRetryTimeoutUnlockEnable" + }, { + "name" : "xaerNotaRetryTimeout" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setServicePort", + "parameterTypes" : [ "java.lang.Integer" ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.ServerRateLimitProperties", + "fields" : [ { + "name" : "bucketTokenMaxNum" + }, { + "name" : "bucketTokenNumPerSecond" + }, { + "name" : "enable" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.ServerRecoveryProperties", + "fields" : [ { + "name" : "asyncCommittingRetryPeriod" + }, { + "name" : "committingRetryPeriod" + }, { + "name" : "rollbackingRetryPeriod" + }, { + "name" : "timeoutRetryPeriod" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.ServerUndoProperties", + "fields" : [ { + "name" : "logDeletePeriod" + }, { + "name" : "logSaveDays" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.filter.ServerHttpFilterXssProperties", + "fields" : [ { + "name" : "keywords" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.raft.ServerRaftProperties", + "fields" : [ { + "name" : "group" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.raft.ServerRaftSSLClientProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.raft.ServerRaftSSLProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.raft.ServerRaftSSLServerProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.session.SessionProperties", + "fields" : [ { + "name" : "enableBranchAsyncRemove" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.store.DbcpProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.store.DruidProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.store.HikariProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.store.StoreDBProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.store.StoreFileProperties", + "fields" : [ { + "name" : "dir" + }, { + "name" : "fileWriteBufferCacheSize" + }, { + "name" : "flushDiskMode" + }, { + "name" : "maxBranchSessionSize" + }, { + "name" : "maxGlobalSessionSize" + }, { + "name" : "sessionReloadReadSize" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.store.StoreProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setMode", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.store.StoreProperties$Lock", + "fields" : [ { + "name" : "mode" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.store.StoreProperties$Session", + "fields" : [ { + "name" : "mode" + } ], + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.store.StoreRedisProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.store.StoreRedisProperties$Sentinel", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.properties.server.store.StoreRedisProperties$Single", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.provider.SpringApplicationContextProvider" + }, { + "type" : "org.apache.seata.spring.boot.autoconfigure.provider.SpringBootConfigurationProvider", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.aspectj.weaver.Advice" + }, { + "type" : "org.crac.Core" + }, { + "type" : "org.eclipse.core.runtime.FileLocator" + }, { + "type" : "org.jboss.logging.Logger" + }, { + "type" : "org.osgi.framework.FrameworkUtil" + }, { + "type" : "org.reactivestreams.Publisher" + }, { + "type" : "org.slf4j.bridge.SLF4JBridgeHandler" + }, { + "type" : "org.slf4j.helpers.Log4jLoggerFactory" + }, { + "type" : "org.springframework.aop.SpringProxy" + }, { + "type" : "org.springframework.aop.TargetClassAware" + }, { + "type" : "org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor" + }, { + "type" : "org.springframework.aop.framework.Advised" + }, { + "type" : "org.springframework.aop.framework.AopConfigException" + }, { + "type" : "org.springframework.aop.framework.AopInfrastructureBean" + }, { + "type" : "org.springframework.aop.framework.ProxyConfig", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setProxyTargetClass", + "parameterTypes" : [ "boolean" ] + } ] + }, { + "type" : "org.springframework.aop.framework.ProxyProcessorSupport", + "methods" : [ { + "name" : "setOrder", + "parameterTypes" : [ "int" ] + } ] + }, { + "type" : "org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator" + }, { + "type" : "org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator" + }, { + "type" : "org.springframework.aop.framework.autoproxy.AbstractBeanFactoryAwareAdvisingPostProcessor" + }, { + "type" : "org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.aot.hint.annotation.Reflective" + }, { + "type" : "org.springframework.beans.factory.Aware" + }, { + "type" : "org.springframework.beans.factory.BeanClassLoaderAware" + }, { + "type" : "org.springframework.beans.factory.BeanFactoryAware" + }, { + "type" : "org.springframework.beans.factory.BeanNameAware" + }, { + "type" : "org.springframework.beans.factory.DisposableBean" + }, { + "type" : "org.springframework.beans.factory.FactoryBean" + }, { + "type" : "org.springframework.beans.factory.InitializingBean" + }, { + "type" : "org.springframework.beans.factory.annotation.Autowired" + }, { + "type" : "org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.beans.factory.annotation.Value" + }, { + "type" : "org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor" + }, { + "type" : "org.springframework.beans.factory.aot.BeanRegistrationAotProcessor" + }, { + "type" : "org.springframework.beans.factory.config.BeanFactoryPostProcessor" + }, { + "type" : "org.springframework.beans.factory.config.BeanPostProcessor" + }, { + "type" : "org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor" + }, { + "type" : "org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor" + }, { + "type" : "org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor" + }, { + "type" : "org.springframework.boot.ApplicationProperties", + "methods" : [ { + "name" : "setWebApplicationType", + "parameterTypes" : [ "org.springframework.boot.WebApplicationType" ] + } ] + }, { + "type" : "org.springframework.boot.ClearCachesApplicationListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.CommandLineRunner" + }, { + "type" : "org.springframework.boot.Runner" + }, { + "type" : "org.springframework.boot.SpringBootConfiguration" + }, { + "type" : "org.springframework.boot.WebApplicationTypeEditor" + }, { + "type" : "org.springframework.boot.ansi.AnsiOutput$Enabled" + }, { + "type" : "org.springframework.boot.autoconfigure.AutoConfiguration" + }, { + "type" : "org.springframework.boot.autoconfigure.AutoConfigurationExcludeFilter", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.AutoConfigurationImportSelector", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.AutoConfigurationPackage" + }, { + "type" : "org.springframework.boot.autoconfigure.AutoConfigurationPackages$BasePackages", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.String[]" ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.AutoConfigureAfter" + }, { + "type" : "org.springframework.boot.autoconfigure.AutoConfigureBefore" + }, { + "type" : "org.springframework.boot.autoconfigure.AutoConfigureOrder" + }, { + "type" : "org.springframework.boot.autoconfigure.EnableAutoConfiguration" + }, { + "type" : "org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.SpringBootApplication" + }, { + "type" : "org.springframework.boot.autoconfigure.aop.AopAutoConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "forceAutoProxyCreatorToUseClassProxying", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "applicationAvailability", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.condition.ConditionalOnBean" + }, { + "type" : "org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty" + }, { + "type" : "org.springframework.boot.autoconfigure.condition.ConditionalOnClass" + }, { + "type" : "org.springframework.boot.autoconfigure.condition.ConditionalOnExpression" + }, { + "type" : "org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean" + }, { + "type" : "org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass" + }, { + "type" : "org.springframework.boot.autoconfigure.condition.ConditionalOnProperty" + }, { + "type" : "org.springframework.boot.autoconfigure.condition.ConditionalOnResource" + }, { + "type" : "org.springframework.boot.autoconfigure.condition.ConditionalOnThreading" + }, { + "type" : "org.springframework.boot.autoconfigure.condition.OnBeanCondition", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.condition.OnClassCondition", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.condition.OnExpressionCondition", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.condition.OnPropertyCondition", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.condition.OnResourceCondition", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.condition.OnThreadingCondition", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.condition.SearchStrategy" + }, { + "type" : "org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "defaultLifecycleProcessor", + "parameterTypes" : [ "org.springframework.boot.autoconfigure.context.LifecycleProperties" ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.context.LifecycleProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration$ResourceBundleCondition", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "propertySourcesPlaceholderConfigurer", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.springframework.boot.autoconfigure.info.ProjectInfoProperties" ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration$GitResourceAvailableCondition", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.info.ProjectInfoProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.preinitialize.BackgroundPreinitializingApplicationListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.preinitialize.CharsetsBackgroundPreinitializer", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.preinitialize.ConversionServiceBackgroundPreinitializer", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.ssl.FileWatcher" + }, { + "type" : "org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.springframework.core.io.ResourceLoader", "org.springframework.boot.autoconfigure.ssl.SslProperties" ] + }, { + "name" : "fileWatcher", + "parameterTypes" : [ ] + }, { + "name" : "sslBundleRegistry", + "parameterTypes" : [ "org.springframework.beans.factory.ObjectProvider" ] + }, { + "name" : "sslPropertiesSslBundleRegistrar", + "parameterTypes" : [ "org.springframework.boot.autoconfigure.ssl.FileWatcher" ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.ssl.SslBundleRegistrar" + }, { + "type" : "org.springframework.boot.autoconfigure.ssl.SslProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.ssl.SslPropertiesBundleRegistrar" + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskExecutionProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$ApplicationTaskExecutorAsyncConfigurer" + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$AsyncConfigurerConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "applicationTaskExecutorAsyncConfigurer", + "parameterTypes" : [ "org.springframework.beans.factory.BeanFactory" ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$AsyncConfigurerWrapperConfiguration" + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$BootstrapExecutorConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "bootstrapExecutorAliasPostProcessor", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$OnExecutorCondition", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$SimpleAsyncTaskExecutorBuilderConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.springframework.boot.autoconfigure.task.TaskExecutionProperties", "org.springframework.beans.factory.ObjectProvider", "org.springframework.beans.factory.ObjectProvider" ] + }, { + "name" : "simpleAsyncTaskExecutorBuilder", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$TaskExecutorConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "applicationTaskExecutor", + "parameterTypes" : [ "org.springframework.boot.task.ThreadPoolTaskExecutorBuilder" ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$ThreadPoolTaskExecutorBuilderConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "threadPoolTaskExecutorBuilder", + "parameterTypes" : [ "org.springframework.boot.autoconfigure.task.TaskExecutionProperties", "org.springframework.beans.factory.ObjectProvider", "org.springframework.beans.factory.ObjectProvider" ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$SimpleAsyncTaskSchedulerBuilderConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.springframework.boot.autoconfigure.task.TaskSchedulingProperties", "org.springframework.beans.factory.ObjectProvider", "org.springframework.beans.factory.ObjectProvider" ] + }, { + "name" : "simpleAsyncTaskSchedulerBuilder", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$TaskSchedulerConfiguration" + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$ThreadPoolTaskSchedulerBuilderConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "threadPoolTaskSchedulerBuilder", + "parameterTypes" : [ "org.springframework.boot.autoconfigure.task.TaskSchedulingProperties", "org.springframework.beans.factory.ObjectProvider", "org.springframework.beans.factory.ObjectProvider" ] + } ] + }, { + "type" : "org.springframework.boot.autoconfigure.task.TaskSchedulingProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.availability.ApplicationAvailability" + }, { + "type" : "org.springframework.boot.availability.ApplicationAvailabilityBean" + }, { + "type" : "org.springframework.boot.builder.ParentContextCloserApplicationListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.springframework.boot.logging.DeferredLogFactory" ] + } ] + }, { + "type" : "org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.ContextIdApplicationContextInitializer", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.FileEncodingApplicationListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.TypeExcludeFilter", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.springframework.boot.logging.DeferredLogFactory", "org.springframework.boot.bootstrap.ConfigurableBootstrapContext" ] + } ] + }, { + "type" : "org.springframework.boot.context.config.ConfigDataLocation[]" + }, { + "type" : "org.springframework.boot.context.config.ConfigDataNotFoundAction" + }, { + "type" : "org.springframework.boot.context.config.ConfigDataProperties" + }, { + "type" : "org.springframework.boot.context.config.ConfigTreeConfigDataLoader", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.springframework.core.io.ResourceLoader" ] + } ] + }, { + "type" : "org.springframework.boot.context.config.StandardConfigDataLoader", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.config.StandardConfigDataLocationResolver", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.springframework.boot.logging.DeferredLogFactory", "org.springframework.boot.context.properties.bind.Binder", "org.springframework.core.io.ResourceLoader" ] + } ] + }, { + "type" : "org.springframework.boot.context.config.SystemEnvironmentConfigDataLoader", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.config.SystemEnvironmentConfigDataLocationResolver", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.event.EventPublishingRunListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.springframework.boot.SpringApplication", "java.lang.String[]" ] + } ] + }, { + "type" : "org.springframework.boot.context.logging.LoggingApplicationListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.properties.BoundConfigurationProperties", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.properties.ConfigurationProperties" + }, { + "type" : "org.springframework.boot.context.properties.ConfigurationPropertiesBinder$ConfigurationPropertiesBinderFactory", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.properties.ConfigurationPropertiesSource" + }, { + "type" : "org.springframework.boot.context.properties.EnableConfigurationProperties" + }, { + "type" : "org.springframework.boot.context.properties.EnableConfigurationPropertiesRegistrar", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.context.properties.NestedConfigurationProperty" + }, { + "type" : "org.springframework.boot.context.properties.bind.Name" + }, { + "type" : "org.springframework.boot.context.properties.bind.Nested" + }, { + "type" : "org.springframework.boot.env.PropertiesPropertySourceLoader", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.env.YamlPropertySourceLoader", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.io.Base64ProtocolResolver", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.io.ClassPathResourceFilePathResolver", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.io.ProtocolResolverApplicationContextInitializer", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.loader.launch.LaunchedClassLoader" + }, { + "type" : "org.springframework.boot.logging.java.JavaLoggingSystem$Factory", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.logging.log4j2.Log4J2LoggingSystem$Factory", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.logging.log4j2.SpringBootPropertySource" + }, { + "type" : "org.springframework.boot.logging.logback.ColorConverter", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.logging.logback.LogbackLoggingSystem$Factory", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.logging.logback.RootLogLevelConfigurator" + }, { + "type" : "org.springframework.boot.ssl.DefaultSslBundleRegistry" + }, { + "type" : "org.springframework.boot.ssl.SslBundleRegistry" + }, { + "type" : "org.springframework.boot.ssl.SslBundles" + }, { + "type" : "org.springframework.boot.support.AnsiOutputApplicationListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.support.EnvironmentPostProcessorApplicationListener", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.support.RandomValuePropertySourceEnvironmentPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "org.springframework.boot.logging.DeferredLogFactory" ] + } ] + }, { + "type" : "org.springframework.boot.support.SpringApplicationJsonEnvironmentPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.support.SystemEnvironmentPropertySourceEnvironmentPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.task.SimpleAsyncTaskExecutorBuilder" + }, { + "type" : "org.springframework.boot.task.SimpleAsyncTaskSchedulerBuilder" + }, { + "type" : "org.springframework.boot.task.ThreadPoolTaskExecutorBuilder" + }, { + "type" : "org.springframework.boot.task.ThreadPoolTaskSchedulerBuilder" + }, { + "type" : "org.springframework.boot.thread.Threading" + }, { + "type" : "org.springframework.boot.validation.beanvalidation.MethodValidationExcludeFilter", + "methods" : [ { + "name" : "byAnnotation", + "parameterTypes" : [ "java.lang.Class" ] + } ] + }, { + "type" : "org.springframework.boot.web.context.reactive.FilteredReactiveWebContextResourceFilePathResolver", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.web.context.servlet.ServletContextResourceFilePathResolver", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.web.server.autoconfigure.ServerProperties", + "methods" : [ { + "name" : "setPort", + "parameterTypes" : [ "java.lang.Integer" ] + } ] + }, { + "type" : "org.springframework.boot.web.server.context.ServerPortInfoApplicationContextInitializer", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.web.server.reactive.context.ReactiveWebServerApplicationContextFactory", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.boot.web.server.servlet.context.ServletWebServerApplicationContextFactory", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.cglib.proxy.Dispatcher" + }, { + "type" : "org.springframework.cglib.proxy.MethodInterceptor" + }, { + "type" : "org.springframework.cglib.proxy.NoOp" + }, { + "type" : "org.springframework.context.ApplicationContextAware" + }, { + "type" : "org.springframework.context.ApplicationListener" + }, { + "type" : "org.springframework.context.ApplicationStartupAware" + }, { + "type" : "org.springframework.context.EnvironmentAware" + }, { + "type" : "org.springframework.context.Lifecycle" + }, { + "type" : "org.springframework.context.LifecycleProcessor" + }, { + "type" : "org.springframework.context.Phased" + }, { + "type" : "org.springframework.context.ResourceLoaderAware" + }, { + "type" : "org.springframework.context.SmartLifecycle" + }, { + "type" : "org.springframework.context.annotation.AnnotationScopeMetadataResolver", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.context.annotation.Bean" + }, { + "type" : "org.springframework.context.annotation.CommonAnnotationBeanPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.context.annotation.ComponentScan" + }, { + "type" : "org.springframework.context.annotation.ComponentScan$Filter" + }, { + "type" : "org.springframework.context.annotation.Conditional" + }, { + "type" : "org.springframework.context.annotation.Configuration" + }, { + "type" : "org.springframework.context.annotation.ConfigurationClassEnhancer$EnhancedConfiguration" + }, { + "type" : "org.springframework.context.annotation.ConfigurationClassPostProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setMetadataReaderFactory", + "parameterTypes" : [ "org.springframework.core.type.classreading.MetadataReaderFactory" ] + } ] + }, { + "type" : "org.springframework.context.annotation.Import" + }, { + "type" : "org.springframework.context.annotation.ImportAware" + }, { + "type" : "org.springframework.context.annotation.ImportRuntimeHints" + }, { + "type" : "org.springframework.context.annotation.Lazy" + }, { + "type" : "org.springframework.context.annotation.Primary" + }, { + "type" : "org.springframework.context.annotation.Role" + }, { + "type" : "org.springframework.context.event.DefaultEventListenerFactory", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.context.event.EventListener" + }, { + "type" : "org.springframework.context.event.EventListenerMethodProcessor", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.context.support.DefaultLifecycleProcessor" + }, { + "type" : "org.springframework.context.support.PropertySourcesPlaceholderConfigurer" + }, { + "type" : "org.springframework.core.Ordered" + }, { + "type" : "org.springframework.core.PriorityOrdered" + }, { + "type" : "org.springframework.core.annotation.AliasFor" + }, { + "type" : "org.springframework.core.annotation.AnnotationAttributes[]" + }, { + "type" : "org.springframework.core.annotation.Order" + }, { + "type" : "org.springframework.core.task.AsyncTaskExecutor" + }, { + "type" : "org.springframework.core.task.TaskExecutor" + }, { + "type" : "org.springframework.core.type.classreading.CachingMetadataReaderFactory" + }, { + "type" : "org.springframework.core.type.classreading.MetadataReaderFactory" + }, { + "type" : "org.springframework.jmx.export.MBeanExporter" + }, { + "type" : "org.springframework.scheduling.SchedulingTaskExecutor" + }, { + "type" : "org.springframework.scheduling.annotation.AbstractAsyncConfiguration", + "methods" : [ { + "name" : "setConfigurers", + "parameterTypes" : [ "org.springframework.beans.factory.ObjectProvider" ] + } ] + }, { + "type" : "org.springframework.scheduling.annotation.Async" + }, { + "type" : "org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor" + }, { + "type" : "org.springframework.scheduling.annotation.AsyncConfigurationSelector", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.scheduling.annotation.AsyncConfigurer" + }, { + "type" : "org.springframework.scheduling.annotation.EnableAsync" + }, { + "type" : "org.springframework.scheduling.annotation.ProxyAsyncConfiguration", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "asyncAdvisor", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.scheduling.concurrent.CustomizableThreadFactory" + }, { + "type" : "org.springframework.scheduling.concurrent.ExecutorConfigurationSupport" + }, { + "type" : "org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" + }, { + "type" : "org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler" + }, { + "type" : "org.springframework.stereotype.Component" + }, { + "type" : "org.springframework.stereotype.Controller" + }, { + "type" : "org.springframework.stereotype.Indexed" + }, { + "type" : "org.springframework.util.ConcurrentReferenceHashMap$Segment[]" + }, { + "type" : "org.springframework.util.CustomizableThreadCreator" + }, { + "type" : "org.springframework.web.bind.annotation.ControllerAdvice" + }, { + "type" : "org.springframework.web.bind.annotation.DeleteMapping", + "methods" : [ { + "name" : "value", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.web.bind.annotation.ExceptionHandler" + }, { + "type" : "org.springframework.web.bind.annotation.GetMapping", + "methods" : [ { + "name" : "value", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.web.bind.annotation.Mapping" + }, { + "type" : "org.springframework.web.bind.annotation.PostMapping", + "methods" : [ { + "name" : "value", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.web.bind.annotation.PutMapping", + "methods" : [ { + "name" : "value", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.web.bind.annotation.RequestMapping", + "methods" : [ { + "name" : "value", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.springframework.web.bind.annotation.RequestMethod[]" + }, { + "type" : "org.springframework.web.bind.annotation.ResponseBody" + }, { + "type" : "org.springframework.web.bind.annotation.RestController" + }, { + "type" : "org.springframework.web.context.support.ServletContextResource" + }, { + "type" : "org.yaml.snakeyaml.Yaml" + }, { + "type" : "short[]" + }, { + "type" : "sun.management.VMManagementImpl", + "jniAccessible" : true, + "fields" : [ { + "name" : "compTimeMonitoringSupport" + }, { + "name" : "currentThreadCpuTimeSupport" + }, { + "name" : "objectMonitorUsageSupport" + }, { + "name" : "otherThreadCpuTimeSupport" + }, { + "name" : "remoteDiagnosticCommandsSupport" + }, { + "name" : "synchronizerUsageSupport" + }, { + "name" : "threadAllocatedMemorySupport" + }, { + "name" : "threadContentionMonitoringSupport" + } ] + }, { + "type" : "sun.misc.Unsafe", + "fields" : [ { + "name" : "theUnsafe" + } ], + "methods" : [ { + "name" : "invokeCleaner", + "parameterTypes" : [ "java.nio.ByteBuffer" ] + } ] + }, { + "type" : "sun.nio.ch.SelectorImpl", + "fields" : [ { + "name" : "publicSelectedKeys" + }, { + "name" : "selectedKeys" + } ] + }, { + "type" : "sun.reflect.ReflectionFactory", + "methods" : [ { + "name" : "getReflectionFactory", + "parameterTypes" : [ ] + }, { + "name" : "newConstructorForSerialization", + "parameterTypes" : [ "java.lang.Class", "java.lang.reflect.Constructor" ] + } ] + }, { + "type" : "sun.security.provider.NativePRNG", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.security.SecureRandomParameters" ] + } ] + }, { + "type" : "sun.security.provider.SHA", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "sun.text.resources.cldr.FormatData" + }, { + "type" : "sun.text.resources.cldr.FormatData_en" + }, { + "type" : "sun.text.resources.cldr.FormatData_en_US" + }, { + "type" : "sun.util.resources.cldr.CalendarData" + }, { + "type" : { + "proxy" : [ "java.lang.reflect.ParameterizedType", "org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy", "java.io.Serializable" ] + } + }, { + "type" : { + "proxy" : [ "java.lang.reflect.WildcardType", "org.springframework.core.SerializableTypeWrapper$SerializableTypeProxy", "java.io.Serializable" ] + } + }, { + "type" : { + "proxy" : [ "org.apache.seata.config.Configuration" ] + } + }, { + "type" : { + "proxy" : [ "org.springframework.boot.context.properties.ConfigurationProperties" ] + } + }, { + "type" : { + "proxy" : [ "org.springframework.context.event.EventListener" ] + } + }, { + "type" : { + "lambda" : { + "declaringClass" : "org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$ClassProxyingConfiguration", + "interfaces" : [ "org.springframework.beans.factory.config.BeanFactoryPostProcessor" ] + } + } + }, { + "type" : { + "lambda" : { + "declaringClass" : "org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$BootstrapExecutorConfiguration", + "interfaces" : [ "org.springframework.beans.factory.config.BeanFactoryPostProcessor" ] + } + } + }, { + "type" : { + "lambda" : { + "declaringClass" : "org.springframework.boot.validation.beanvalidation.MethodValidationExcludeFilter", + "interfaces" : [ "org.springframework.boot.validation.beanvalidation.MethodValidationExcludeFilter" ] + } + } + }, { + "type" : "io.netty.channel.ChannelException", + "jniAccessible" : true + }, { + "type" : "io.netty.channel.DefaultFileRegion", + "jniAccessible" : true, + "fields" : [ { + "name" : "file" + }, { + "name" : "transferred" + } ] + }, { + "type" : "io.netty.channel.epoll.EpollServerSocketChannel", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "io.netty.channel.epoll.LinuxSocket", + "jniAccessible" : true + }, { + "type" : "io.netty.channel.epoll.Native", + "jniAccessible" : true + }, { + "type" : "io.netty.channel.epoll.NativeDatagramPacketArray$NativeDatagramPacket", + "jniAccessible" : true, + "fields" : [ { + "name" : "count" + }, { + "name" : "memoryAddress" + }, { + "name" : "recipientAddr" + }, { + "name" : "recipientAddrLen" + }, { + "name" : "recipientPort" + }, { + "name" : "recipientScopeId" + }, { + "name" : "segmentSize" + }, { + "name" : "senderAddr" + }, { + "name" : "senderAddrLen" + }, { + "name" : "senderPort" + }, { + "name" : "senderScopeId" + } ] + }, { + "type" : "io.netty.channel.epoll.NativeStaticallyReferencedJniMethods", + "jniAccessible" : true + }, { + "type" : "io.netty.channel.unix.Buffer", + "jniAccessible" : true + }, { + "type" : "io.netty.channel.unix.DatagramSocketAddress", + "jniAccessible" : true, + "methods" : [ { + "name" : "", + "parameterTypes" : [ "byte[]", "int", "int", "int", "io.netty.channel.unix.DatagramSocketAddress" ] + } ] + }, { + "type" : "io.netty.channel.unix.DomainDatagramSocketAddress", + "jniAccessible" : true, + "methods" : [ { + "name" : "", + "parameterTypes" : [ "byte[]", "int", "io.netty.channel.unix.DomainDatagramSocketAddress" ] + } ] + }, { + "type" : "io.netty.channel.unix.ErrorsStaticallyReferencedJniMethods", + "jniAccessible" : true + }, { + "type" : "io.netty.channel.unix.FileDescriptor", + "jniAccessible" : true + }, { + "type" : "io.netty.channel.unix.LimitsStaticallyReferencedJniMethods", + "jniAccessible" : true + }, { + "type" : "io.netty.channel.unix.PeerCredentials", + "jniAccessible" : true, + "methods" : [ { + "name" : "", + "parameterTypes" : [ "int", "int", "int[]" ] + } ] + }, { + "type" : "io.netty.channel.unix.Socket", + "jniAccessible" : true + }, { + "type" : "io.netty.util.internal.NativeLibraryUtil", + "methods" : [ { + "name" : "loadLibrary", + "parameterTypes" : [ "java.lang.String", "boolean" ] + } ] + }, { + "type" : "java.io.FileDescriptor", + "jniAccessible" : true, + "fields" : [ { + "name" : "fd" + } ] + }, { + "type" : "java.io.IOException", + "jniAccessible" : true + }, { + "type" : "java.lang.OutOfMemoryError", + "jniAccessible" : true + }, { + "type" : "java.lang.foreign.SegmentAllocator", + "methods" : [ { + "name" : "allocate", + "parameterTypes" : [ "long" ] + } ] + }, { + "type" : "java.net.InetSocketAddress", + "jniAccessible" : true, + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.String", "int" ] + }, { + "name" : "getHostString", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.net.PortUnreachableException", + "jniAccessible" : true + }, { + "type" : "java.nio.Buffer", + "jniAccessible" : true, + "fields" : [ { + "name" : "limit" + }, { + "name" : "position" + }, { + "name" : "address" + } ], + "methods" : [ { + "name" : "limit", + "parameterTypes" : [ ] + }, { + "name" : "position", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.nio.DirectByteBuffer" + }, { + "type" : "java.nio.channels.ClosedChannelException", + "jniAccessible" : true, + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.nio.channels.FileChannel" + }, { + "type" : "org.springframework.aot.generate.Generated" + }, { + "type" : "org.springframework.boot.loader.net.protocol.nested.Handler", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "sun.net.www.protocol.jar.Handler", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "sun.nio.ch.FileChannelImpl", + "jniAccessible" : true, + "fields" : [ { + "name" : "fd" + } ] + }, { + "type" : "io.netty.handler.codec.http.HttpObjectAggregator" + }, { + "type" : "io.netty.handler.codec.http.HttpServerCodec" + }, { + "type" : "io.netty.handler.codec.http.HttpServerUpgradeHandler" + }, { + "type" : "org.apache.seata.core.protocol.detector.HttpDetector$1" + }, { + "type" : "org.apache.seata.core.protocol.detector.HttpDetector$2" + }, { + "type" : "org.apache.seata.core.rpc.netty.http.HttpDispatchHandler" + }, { + "type" : "android.app.Application" + }, { + "type" : "ch.qos.logback.classic.Logger" + }, { + "type" : "com.alibaba.nacos.api.ability.ClientAbilities", + "methods" : [ { + "name" : "getConfigAbility", + "parameterTypes" : [ ] + }, { + "name" : "getNamingAbility", + "parameterTypes" : [ ] + }, { + "name" : "getRemoteAbility", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.config.ability.ClientConfigAbility", + "methods" : [ { + "name" : "isSupportRemoteMetrics", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.config.remote.request.AbstractConfigRequest", + "methods" : [ { + "name" : "getModule", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.config.remote.request.ClientConfigMetricRequest" + }, { + "type" : "com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest", + "fields" : [ { + "name" : "configListenContexts" + }, { + "name" : "listen" + } ], + "methods" : [ { + "name" : "getConfigListenContexts", + "parameterTypes" : [ ] + }, { + "name" : "isListen", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.config.remote.request.ConfigBatchListenRequest$ConfigListenContext", + "fields" : [ { + "name" : "dataId" + }, { + "name" : "group" + }, { + "name" : "md5" + }, { + "name" : "tenant" + } ], + "methods" : [ { + "name" : "getDataId", + "parameterTypes" : [ ] + }, { + "name" : "getGroup", + "parameterTypes" : [ ] + }, { + "name" : "getMd5", + "parameterTypes" : [ ] + }, { + "name" : "getTenant", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.config.remote.request.ConfigChangeNotifyRequest" + }, { + "type" : "com.alibaba.nacos.api.config.remote.request.ConfigPublishRequest" + }, { + "type" : "com.alibaba.nacos.api.config.remote.request.ConfigQueryRequest", + "fields" : [ { + "name" : "dataId" + }, { + "name" : "group" + }, { + "name" : "tag" + }, { + "name" : "tenant" + } ], + "methods" : [ { + "name" : "getDataId", + "parameterTypes" : [ ] + }, { + "name" : "getGroup", + "parameterTypes" : [ ] + }, { + "name" : "getTag", + "parameterTypes" : [ ] + }, { + "name" : "getTenant", + "parameterTypes" : [ ] + }, { + "name" : "isNotify", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.config.remote.request.ConfigRemoveRequest" + }, { + "type" : "com.alibaba.nacos.api.config.remote.request.cluster.ConfigChangeClusterSyncRequest" + }, { + "type" : "com.alibaba.nacos.api.config.remote.response.ClientConfigMetricResponse" + }, { + "type" : "com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setChangedConfigs", + "parameterTypes" : [ "java.util.List" ] + } ] + }, { + "type" : "com.alibaba.nacos.api.config.remote.response.ConfigChangeBatchListenResponse$ConfigContext" + }, { + "type" : "com.alibaba.nacos.api.config.remote.response.ConfigChangeNotifyResponse" + }, { + "type" : "com.alibaba.nacos.api.config.remote.response.ConfigPublishResponse" + }, { + "type" : "com.alibaba.nacos.api.config.remote.response.ConfigQueryResponse", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setBeta", + "parameterTypes" : [ "boolean" ] + }, { + "name" : "setLastModified", + "parameterTypes" : [ "long" ] + } ] + }, { + "type" : "com.alibaba.nacos.api.config.remote.response.ConfigRemoveResponse" + }, { + "type" : "com.alibaba.nacos.api.config.remote.response.cluster.ConfigChangeClusterSyncResponse" + }, { + "type" : "com.alibaba.nacos.api.naming.ability.ClientNamingAbility", + "methods" : [ { + "name" : "isSupportDeltaPush", + "parameterTypes" : [ ] + }, { + "name" : "isSupportRemoteMetric", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.naming.pojo.Instance", + "methods" : [ { + "name" : "getClusterName", + "parameterTypes" : [ ] + }, { + "name" : "getInstanceHeartBeatInterval", + "parameterTypes" : [ ] + }, { + "name" : "getInstanceHeartBeatTimeOut", + "parameterTypes" : [ ] + }, { + "name" : "getInstanceId", + "parameterTypes" : [ ] + }, { + "name" : "getInstanceIdGenerator", + "parameterTypes" : [ ] + }, { + "name" : "getIp", + "parameterTypes" : [ ] + }, { + "name" : "getIpDeleteTimeout", + "parameterTypes" : [ ] + }, { + "name" : "getMetadata", + "parameterTypes" : [ ] + }, { + "name" : "getPort", + "parameterTypes" : [ ] + }, { + "name" : "getServiceName", + "parameterTypes" : [ ] + }, { + "name" : "getWeight", + "parameterTypes" : [ ] + }, { + "name" : "isEnabled", + "parameterTypes" : [ ] + }, { + "name" : "isEphemeral", + "parameterTypes" : [ ] + }, { + "name" : "isHealthy", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.naming.remote.request.AbstractNamingRequest", + "methods" : [ { + "name" : "getGroupName", + "parameterTypes" : [ ] + }, { + "name" : "getModule", + "parameterTypes" : [ ] + }, { + "name" : "getNamespace", + "parameterTypes" : [ ] + }, { + "name" : "getServiceName", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.naming.remote.request.InstanceRequest", + "methods" : [ { + "name" : "getInstance", + "parameterTypes" : [ ] + }, { + "name" : "getType", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.naming.remote.request.NotifySubscriberRequest" + }, { + "type" : "com.alibaba.nacos.api.naming.remote.request.ServiceListRequest" + }, { + "type" : "com.alibaba.nacos.api.naming.remote.request.ServiceQueryRequest" + }, { + "type" : "com.alibaba.nacos.api.naming.remote.request.SubscribeServiceRequest" + }, { + "type" : "com.alibaba.nacos.api.naming.remote.response.InstanceResponse", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setType", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "com.alibaba.nacos.api.naming.remote.response.NotifySubscriberResponse" + }, { + "type" : "com.alibaba.nacos.api.naming.remote.response.QueryServiceResponse" + }, { + "type" : "com.alibaba.nacos.api.naming.remote.response.ServiceListResponse" + }, { + "type" : "com.alibaba.nacos.api.naming.remote.response.SubscribeServiceResponse" + }, { + "type" : "com.alibaba.nacos.api.remote.ability.ClientRemoteAbility", + "methods" : [ { + "name" : "isSupportRemoteConnection", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.remote.request.ClientDetectionRequest" + }, { + "type" : "com.alibaba.nacos.api.remote.request.ConnectResetRequest" + }, { + "type" : "com.alibaba.nacos.api.remote.request.ConnectionSetupRequest", + "methods" : [ { + "name" : "getAbilities", + "parameterTypes" : [ ] + }, { + "name" : "getClientVersion", + "parameterTypes" : [ ] + }, { + "name" : "getLabels", + "parameterTypes" : [ ] + }, { + "name" : "getTenant", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.remote.request.HealthCheckRequest" + }, { + "type" : "com.alibaba.nacos.api.remote.request.InternalRequest", + "methods" : [ { + "name" : "getModule", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.remote.request.PushAckRequest" + }, { + "type" : "com.alibaba.nacos.api.remote.request.Request", + "fields" : [ { + "name" : "headers" + }, { + "name" : "requestId" + } ], + "methods" : [ { + "name" : "getHeaders", + "parameterTypes" : [ ] + }, { + "name" : "getRequestId", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.remote.request.ServerCheckRequest" + }, { + "type" : "com.alibaba.nacos.api.remote.request.ServerLoaderInfoRequest" + }, { + "type" : "com.alibaba.nacos.api.remote.request.ServerReloadRequest" + }, { + "type" : "com.alibaba.nacos.api.remote.request.ServerRequest" + }, { + "type" : "com.alibaba.nacos.api.remote.response.ClientDetectionResponse" + }, { + "type" : "com.alibaba.nacos.api.remote.response.ConnectResetResponse" + }, { + "type" : "com.alibaba.nacos.api.remote.response.ErrorResponse" + }, { + "type" : "com.alibaba.nacos.api.remote.response.HealthCheckResponse", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.api.remote.response.Response", + "methods" : [ { + "name" : "setErrorCode", + "parameterTypes" : [ "int" ] + }, { + "name" : "setMessage", + "parameterTypes" : [ "java.lang.String" ] + }, { + "name" : "setResultCode", + "parameterTypes" : [ "int" ] + } ] + }, { + "type" : "com.alibaba.nacos.api.remote.response.ServerCheckResponse", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "setConnectionId", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "com.alibaba.nacos.api.remote.response.ServerLoaderInfoResponse" + }, { + "type" : "com.alibaba.nacos.api.remote.response.ServerReloadResponse" + }, { + "type" : "com.alibaba.nacos.api.remote.PayloadRegistry", + "fields" : [ { + "name" : "REGISTRY_REQUEST" + }, { + "name" : "initialized" + } ] + }, { + "type" : "com.alibaba.nacos.client.config.NacosConfigService", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.util.Properties" ] + } ] + }, { + "type" : "com.alibaba.nacos.client.naming.NacosNamingService", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.util.Properties" ] + } ] + }, { + "type" : "com.alibaba.nacos.common.notify.DefaultPublisher", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture", + "fields" : [ { + "name" : "listeners" + }, { + "name" : "value" + }, { + "name" : "waiters" + } ] + }, { + "type" : "com.alibaba.nacos.shaded.com.google.common.util.concurrent.AbstractFuture$Waiter", + "fields" : [ { + "name" : "next" + }, { + "name" : "thread" + } ] + }, { + "type" : "com.alibaba.nacos.shaded.com.google.protobuf.ExtensionRegistry", + "methods" : [ { + "name" : "getEmptyRegistry", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.internal.CensusStatsModule$ClientCallTracer" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.internal.CensusStatsModule$ClientTracer" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.internal.CensusTracingModule$ClientCallTracer" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.internal.CensusTracingModule$ServerTracer" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.internal.DnsNameResolverProvider" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.internal.JndiResourceResolverFactory", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.internal.PickFirstLoadBalancerProvider" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.internal.SerializingExecutor" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.NettyChannelProvider" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.NettyClientHandler" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$GrpcNegotiationHandler" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.ProtocolNegotiators$WaitUntilActiveHandler" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.grpc.netty.WriteBufferingAndExceptionHandler" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.buffer.AbstractReferenceCountedByteBuf", + "fields" : [ { + "name" : "refCnt" + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.ChannelOutboundBuffer" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelConfig" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$TailContext" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.epoll.Epoll", + "methods" : [ { + "name" : "isAvailable", + "parameterTypes" : [ ] + }, { + "name" : "unavailabilityCause", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.channel.socket.nio.NioSocketChannel", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.DefaultAttributeMap" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.ReferenceCountUtil" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.ResourceLeakDetector$DefaultResourceLeak" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.concurrent.DefaultPromise" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.concurrent.SingleThreadEventExecutor" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields", + "fields" : [ { + "name" : "producerLimit" + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields", + "fields" : [ { + "name" : "consumerIndex" + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields", + "fields" : [ { + "name" : "producerIndex" + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField", + "fields" : [ { + "name" : "consumerIndex" + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField", + "fields" : [ { + "name" : "producerIndex" + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField", + "fields" : [ { + "name" : "producerLimit" + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.override.ContextStorageOverride" + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.util.SecretRoundRobinLoadBalancerProvider$Provider" + }, { + "type" : "com.alibaba.nacos.shaded.io.opencensus.impl.stats.StatsComponentImpl" + }, { + "type" : "com.alibaba.nacos.shaded.io.opencensus.impl.tags.TagsComponentImpl" + }, { + "type" : "com.alibaba.nacos.shaded.io.opencensus.impl.trace.TraceComponentImpl" + }, { + "type" : "com.alibaba.nacos.shaded.io.opencensus.impllite.stats.StatsComponentImplLite" + }, { + "type" : "com.alibaba.nacos.shaded.io.opencensus.impllite.tags.TagsComponentImplLite" + }, { + "type" : "com.alibaba.nacos.shaded.io.opencensus.impllite.trace.TraceComponentImplLite" + }, { + "type" : "com.alibaba.nacos.shaded.io.perfmark.impl.SecretPerfMarkImpl$PerfMarkImpl" + }, { + "type" : "com.sun.jndi.dns.DnsContextFactory" + }, { + "type" : "double" + }, { + "type" : "io.prometheus.client.Striped64" + }, { + "type" : "io.seata.config.ConfigurationProvider" + }, { + "type" : "java.lang.Enum" + }, { + "type" : "java.lang.StringBuilder" + }, { + "type" : "java.lang.invoke.CallSite" + }, { + "type" : "java.lang.reflect.AccessibleObject" + }, { + "type" : "java.nio.Bits", + "fields" : [ { + "name" : "UNALIGNED" + } ] + }, { + "type" : "java.util.List" + }, { + "type" : "java.util.Map" + }, { + "type" : "java.util.concurrent.atomic.LongAdder", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + }, { + "name" : "add", + "parameterTypes" : [ "long" ] + } ] + }, { + "type" : "java.util.function.Function" + }, { + "type" : "java.util.zip.DeflaterInputStream" + }, { + "type" : "javax.naming.directory.InitialDirContext" + }, { + "type" : "libcore.io.Memory" + }, { + "type" : "org.apache.seata.config.apollo.ApolloConfigurationProvider" + }, { + "type" : "org.apache.seata.config.consul.ConsulConfigurationProvider" + }, { + "type" : "org.apache.seata.config.etcd3.EtcdConfigurationProvider" + }, { + "type" : "org.apache.seata.config.nacos.NacosConfigurationProvider", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.config.springcloud.SpringCloudConfigurationProvider" + }, { + "type" : "org.apache.seata.config.zk.ZookeeperConfigurationProvider" + }, { + "type" : "org.robolectric.Robolectric" + }, { + "type" : "org.slf4j.impl.StaticLoggerBinder" + }, { + "type" : "sun.misc.VM" + }, { + "type" : "sun.security.provider.MD5", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.server.NacosPayloadRegistryInitializer", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.alibaba.nacos.shaded.io.grpc.netty.shaded.io.netty.util.internal.NativeLibraryUtil", + "methods" : [ { + "name" : "loadLibrary", + "parameterTypes" : [ "java.lang.String", "boolean" ] + } ] + }, { + "type" : "java.lang.foreign.AddressLayout", + "methods" : [ { + "name" : "byteSize", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.foreign.FunctionDescriptor", + "methods" : [ { + "name" : "of", + "parameterTypes" : [ "java.lang.foreign.MemoryLayout", "java.lang.foreign.MemoryLayout[]" ] + }, { + "name" : "ofVoid", + "parameterTypes" : [ "java.lang.foreign.MemoryLayout[]" ] + } ] + }, { + "type" : "java.lang.foreign.Linker", + "methods" : [ { + "name" : "defaultLookup", + "parameterTypes" : [ ] + }, { + "name" : "downcallHandle", + "parameterTypes" : [ "java.lang.foreign.MemorySegment", "java.lang.foreign.FunctionDescriptor", "java.lang.foreign.Linker$Option[]" ] + }, { + "name" : "nativeLinker", + "parameterTypes" : [ ] + } ] + }, { + "type" : "java.lang.foreign.Linker$Option" + }, { + "type" : "java.lang.foreign.Linker$Option[]" + }, { + "type" : "java.lang.foreign.MemoryLayout" + }, { + "type" : "java.lang.foreign.MemoryLayout[]" + }, { + "type" : "java.lang.foreign.SymbolLookup", + "methods" : [ { + "name" : "findOrThrow", + "parameterTypes" : [ "java.lang.String" ] + } ] + }, { + "type" : "java.lang.foreign.ValueLayout", + "fields" : [ { + "name" : "ADDRESS" + }, { + "name" : "JAVA_LONG" + } ] + }, { + "type" : "java.lang.foreign.ValueLayout$OfLong" + }, { + "type" : "com.alibaba.fastjson.JSONArray" + }, { + "type" : "com.alibaba.fastjson.JSONObject" + }, { + "type" : "com.alibaba.fastjson2.util.TypeUtils$Cache" + }, { + "type" : "com.sun.crypto.provider.AESCipher$General", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.sun.crypto.provider.ARCFOURCipher", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.sun.crypto.provider.DESCipher", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.sun.crypto.provider.DESedeCipher", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "com.sun.crypto.provider.GaloisCounterMode$AESGCM", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "io.seata.common.json.JsonCodec" + }, { + "type" : "io.seata.common.json.JsonSerializer" + }, { + "type" : "java.security.AlgorithmParametersSpi" + }, { + "type" : "java.security.KeyStoreSpi" + }, { + "type" : "java.sql.Time" + }, { + "type" : "java.util.Collections$UnmodifiableCollection" + }, { + "type" : "java.util.Collections$UnmodifiableMap" + }, { + "type" : "java.util.Deque" + }, { + "type" : "org.apache.seata.common.json.JsonUtilCodec", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.common.json.impl.Fastjson2JsonSerializer" + }, { + "type" : "org.apache.seata.common.json.impl.FastjsonJsonSerializer" + }, { + "type" : "org.apache.seata.common.json.impl.GsonJsonSerializer" + }, { + "type" : "org.apache.seata.common.json.impl.JacksonJsonSerializer", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.common.metadata.ClusterRole" + }, { + "type" : "org.apache.seata.common.metadata.Instance", + "methods" : [ { + "name" : "getClusterName", + "parameterTypes" : [ ] + }, { + "name" : "getControl", + "parameterTypes" : [ ] + }, { + "name" : "getInternal", + "parameterTypes" : [ ] + }, { + "name" : "getMetadata", + "parameterTypes" : [ ] + }, { + "name" : "getNamespace", + "parameterTypes" : [ ] + }, { + "name" : "getRole", + "parameterTypes" : [ ] + }, { + "name" : "getTerm", + "parameterTypes" : [ ] + }, { + "name" : "getTimestamp", + "parameterTypes" : [ ] + }, { + "name" : "getTransaction", + "parameterTypes" : [ ] + }, { + "name" : "getUnit", + "parameterTypes" : [ ] + }, { + "name" : "getVersion", + "parameterTypes" : [ ] + }, { + "name" : "getWeight", + "parameterTypes" : [ ] + }, { + "name" : "isHealthy", + "parameterTypes" : [ ] + } ] + }, { + "type" : "org.apache.seata.common.metadata.Node$Endpoint", + "methods" : [ { + "name" : "getHost", + "parameterTypes" : [ ] + }, { + "name" : "getPort", + "parameterTypes" : [ ] + } ] + }, { + "type" : "sun.security.pkcs12.PKCS12KeyStore", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "sun.security.provider.X509Factory", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "sun.security.rsa.RSAKeyFactory$Legacy", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "sun.security.ssl.SSLContextImpl$TLSContext", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + }, { + "type" : "sun.security.x509.AuthorityInfoAccessExtension", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Boolean", "java.lang.Object" ] + } ] + }, { + "type" : "sun.security.x509.AuthorityKeyIdentifierExtension", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Boolean", "java.lang.Object" ] + } ] + }, { + "type" : "sun.security.x509.BasicConstraintsExtension", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Boolean", "java.lang.Object" ] + } ] + }, { + "type" : "sun.security.x509.CRLDistributionPointsExtension", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Boolean", "java.lang.Object" ] + } ] + }, { + "type" : "sun.security.x509.CertificatePoliciesExtension", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Boolean", "java.lang.Object" ] + } ] + }, { + "type" : "sun.security.x509.ExtendedKeyUsageExtension", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Boolean", "java.lang.Object" ] + } ] + }, { + "type" : "sun.security.x509.KeyUsageExtension", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Boolean", "java.lang.Object" ] + } ] + }, { + "type" : "sun.security.x509.NetscapeCertTypeExtension", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Boolean", "java.lang.Object" ] + } ] + }, { + "type" : "sun.security.x509.PrivateKeyUsageExtension", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Boolean", "java.lang.Object" ] + } ] + }, { + "type" : "sun.security.x509.SubjectKeyIdentifierExtension", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Boolean", "java.lang.Object" ] + } ] + }, { + "type" : "apple.security.AppleProvider", + "methods" : [ { + "name" : "", + "parameterTypes" : [ ] + } ] + } ], + "resources" : [ { + "glob" : "" + }, { + "glob" : "META-INF/build-info.properties" + }, { + "glob" : "META-INF/seata/org.apache.seata.common.thread.ThreadPoolProvider" + }, { + "glob" : "META-INF/seata/org.apache.seata.config.ExtConfigurationProvider" + }, { + "glob" : "META-INF/seata/org.apache.seata.config.file.FileConfig" + }, { + "glob" : "META-INF/seata/org.apache.seata.core.context.ContextCore" + }, { + "glob" : "META-INF/seata/org.apache.seata.core.rpc.RegisterCheckAuthHandler" + }, { + "glob" : "META-INF/seata/org.apache.seata.core.rpc.hook.RpcHook" + }, { + "glob" : "META-INF/seata/org.apache.seata.core.rpc.netty.http.filter.HttpRequestFilter" + }, { + "glob" : "META-INF/seata/org.apache.seata.core.serializer.Serializer" + }, { + "glob" : "META-INF/seata/org.apache.seata.discovery.registry.RegistryProvider" + }, { + "glob" : "META-INF/seata/org.apache.seata.metrics.exporter.Exporter" + }, { + "glob" : "META-INF/seata/org.apache.seata.metrics.registry.Registry" + }, { + "glob" : "META-INF/seata/org.apache.seata.server.coordinator.AbstractCore" + }, { + "glob" : "META-INF/seata/org.apache.seata.server.limit.ratelimit.RateLimiter" + }, { + "glob" : "META-INF/seata/org.apache.seata.server.lock.LockManager" + }, { + "glob" : "META-INF/seata/org.apache.seata.server.session.SessionManager" + }, { + "glob" : "META-INF/seata/org.apache.seata.server.store.VGroupMappingStoreManager" + }, { + "glob" : "META-INF/services/ch.qos.logback.classic.spi.Configurator" + }, { + "glob" : "META-INF/services/com.sun.net.httpserver.spi.HttpServerProvider" + }, { + "glob" : "META-INF/services/java.net.spi.URLStreamHandlerProvider" + }, { + "glob" : "META-INF/services/java.nio.channels.spi.SelectorProvider" + }, { + "glob" : "META-INF/services/java.time.zone.ZoneRulesProvider" + }, { + "glob" : "META-INF/services/javax.xml.parsers.SAXParserFactory" + }, { + "glob" : "META-INF/services/org.apache.commons.logging.LogFactory" + }, { + "glob" : "META-INF/services/org.apache.logging.log4j.util.PropertySource" + }, { + "glob" : "META-INF/services/org.apache.seata.common.thread.ThreadPoolProvider" + }, { + "glob" : "META-INF/services/org.apache.seata.config.ExtConfigurationProvider" + }, { + "glob" : "META-INF/services/org.apache.seata.config.file.FileConfig" + }, { + "glob" : "META-INF/services/org.apache.seata.core.context.ContextCore" + }, { + "glob" : "META-INF/services/org.apache.seata.core.rpc.RegisterCheckAuthHandler" + }, { + "glob" : "META-INF/services/org.apache.seata.core.rpc.hook.RpcHook" + }, { + "glob" : "META-INF/services/org.apache.seata.core.rpc.netty.http.filter.HttpRequestFilter" + }, { + "glob" : "META-INF/services/org.apache.seata.core.serializer.Serializer" + }, { + "glob" : "META-INF/services/org.apache.seata.discovery.registry.RegistryProvider" + }, { + "glob" : "META-INF/services/org.apache.seata.metrics.exporter.Exporter" + }, { + "glob" : "META-INF/services/org.apache.seata.metrics.registry.Registry" + }, { + "glob" : "META-INF/services/org.apache.seata.server.coordinator.AbstractCore" + }, { + "glob" : "META-INF/services/org.apache.seata.server.limit.ratelimit.RateLimiter" + }, { + "glob" : "META-INF/services/org.apache.seata.server.lock.LockManager" + }, { + "glob" : "META-INF/services/org.apache.seata.server.session.SessionManager" + }, { + "glob" : "META-INF/services/org.apache.seata.server.store.VGroupMappingStoreManager" + }, { + "glob" : "META-INF/services/org.slf4j.spi.SLF4JServiceProvider" + }, { + "glob" : "META-INF/spring-autoconfigure-metadata.properties" + }, { + "glob" : "META-INF/spring.components" + }, { + "glob" : "META-INF/spring.factories" + }, { + "glob" : "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports" + }, { + "glob" : "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.replacements" + }, { + "glob" : "application-default.properties" + }, { + "glob" : "application-default.xml" + }, { + "glob" : "application-default.yaml" + }, { + "glob" : "application-default.yml" + }, { + "glob" : "application.conf" + }, { + "glob" : "application.json" + }, { + "glob" : "application.properties" + }, { + "glob" : "application.xml" + }, { + "glob" : "application.yaml" + }, { + "glob" : "application.yml" + }, { + "glob" : "banner.txt" + }, { + "glob" : "ch/qos/logback/classic/logback-classic-version.properties" + }, { + "glob" : "ch/qos/logback/core/logback-core-version.properties" + }, { + "glob" : "commons-logging.properties" + }, { + "glob" : "config/application-default.properties" + }, { + "glob" : "config/application-default.xml" + }, { + "glob" : "config/application-default.yaml" + }, { + "glob" : "config/application-default.yml" + }, { + "glob" : "config/application.properties" + }, { + "glob" : "config/application.xml" + }, { + "glob" : "config/application.yaml" + }, { + "glob" : "config/application.yml" + }, { + "glob" : "file.conf" + }, { + "glob" : "file.conf.conf" + }, { + "glob" : "file.conf.properties" + }, { + "glob" : "file.conf.yml" + }, { + "glob" : "git.properties" + }, { + "glob" : "log4j2.StatusLogger.properties" + }, { + "glob" : "log4j2.component.properties" + }, { + "glob" : "log4j2.system.properties" + }, { + "glob" : "logback-spring.xml" + }, { + "glob" : "logback-test.xml" + }, { + "glob" : "logback.xml" + }, { + "glob" : "logback/console-appender.xml" + }, { + "glob" : "logback/file-appender.xml" + }, { + "glob" : "messages.properties" + }, { + "glob" : "org/apache/seata" + }, { + "glob" : "org/apache/seata/common/loader/LoadLevel.class" + }, { + "glob" : "org/apache/seata/core/rpc/netty/http/filter/HttpRequestFilter.class" + }, { + "glob" : "org/apache/seata/server/Server.class" + }, { + "glob" : "org/apache/seata/server/ServerRunner.class" + }, { + "glob" : "org/apache/seata/server/cluster/listener/ClusterChangeListener.class" + }, { + "glob" : "org/apache/seata/server/cluster/manager/ClusterWatcherManager.class" + }, { + "glob" : "org/apache/seata/server/config/AsyncConfig.class" + }, { + "glob" : "org/apache/seata/server/config/ServerConfig.class" + }, { + "glob" : "org/apache/seata/server/config/ServerInstanceStrategyConfig.class" + }, { + "glob" : "org/apache/seata/server/console/aop/GlobalExceptionHandlerAdvice.class" + }, { + "glob" : "org/apache/seata/server/console/controller/BranchSessionController.class" + }, { + "glob" : "org/apache/seata/server/console/controller/GlobalLockController.class" + }, { + "glob" : "org/apache/seata/server/console/controller/GlobalSessionController.class" + }, { + "glob" : "org/apache/seata/server/console/impl/AbstractBranchService.class" + }, { + "glob" : "org/apache/seata/server/console/impl/AbstractGlobalService.class" + }, { + "glob" : "org/apache/seata/server/console/impl/AbstractLockService.class" + }, { + "glob" : "org/apache/seata/server/console/impl/AbstractService$CheckResult.class" + }, { + "glob" : "org/apache/seata/server/console/impl/AbstractService.class" + }, { + "glob" : "org/apache/seata/server/console/impl/file/BranchSessionFileServiceImpl.class" + }, { + "glob" : "org/apache/seata/server/console/impl/file/GlobalLockFileServiceImpl.class" + }, { + "glob" : "org/apache/seata/server/console/impl/file/GlobalSessionFileServiceImpl.class" + }, { + "glob" : "org/apache/seata/server/console/service/BranchSessionService.class" + }, { + "glob" : "org/apache/seata/server/console/service/GlobalLockService.class" + }, { + "glob" : "org/apache/seata/server/console/service/GlobalSessionService.class" + }, { + "glob" : "org/apache/seata/server/controller/ClusterController.class" + }, { + "glob" : "org/apache/seata/server/controller/HealthController.class" + }, { + "glob" : "org/apache/seata/server/controller/VGroupMappingController.class" + }, { + "glob" : "org/apache/seata/server/filter/RaftRequestFilter.class" + }, { + "glob" : "org/apache/seata/server/instance/AbstractSeataInstanceStrategy.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/SeataCoreAutoConfiguration.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/http/RestControllerBeanPostProcessor.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/LogProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/ShutdownProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/ThreadFactoryProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/TransportProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/config/ConfigApolloProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/config/ConfigConsulProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/config/ConfigCustomProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/config/ConfigEtcd3Properties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/config/ConfigFileProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/config/ConfigNacosProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/config/ConfigProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/config/ConfigZooKeeperProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryConsulProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryCustomProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryEtcd3Properties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryEurekaProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryNacosProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryNamingServerProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryRaftProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryRedisProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistrySofaProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryZooKeeperProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/MetricsProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/ServerProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/ServerRateLimitProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/ServerRecoveryProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/ServerUndoProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/filter/ServerHttpFilterXssProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/raft/ServerRaftProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/raft/ServerRaftSSLClientProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/raft/ServerRaftSSLProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/raft/ServerRaftSSLServerProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/session/SessionProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/store/DbcpProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/store/DruidProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/store/HikariProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/store/StoreDBProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/store/StoreFileProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/store/StoreProperties$Lock.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/store/StoreProperties$Session.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/store/StoreProperties.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/store/StoreRedisProperties$Sentinel.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/store/StoreRedisProperties$Single.class" + }, { + "glob" : "org/apache/seata/spring/boot/autoconfigure/properties/server/store/StoreRedisProperties.class" + }, { + "glob" : "org/springframework/aot/hint/annotation/Reflective.class" + }, { + "glob" : "org/springframework/beans/factory/Aware.class" + }, { + "glob" : "org/springframework/beans/factory/DisposableBean.class" + }, { + "glob" : "org/springframework/beans/factory/config/BeanPostProcessor.class" + }, { + "glob" : "org/springframework/boot/CommandLineRunner.class" + }, { + "glob" : "org/springframework/boot/Runner.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/AutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/AutoConfigureAfter.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/AutoConfigureBefore.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/AutoConfigureOrder.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/admin/SpringApplicationAdminJmxAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/aop/AopAutoConfiguration$AspectJAutoProxyingConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/aop/AopAutoConfiguration$ClassProxyingConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/aop/AopAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/availability/ApplicationAvailabilityAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/condition/ConditionalOnBean.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/condition/ConditionalOnBooleanProperty.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/condition/ConditionalOnClass.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/condition/ConditionalOnExpression.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBean.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/condition/ConditionalOnMissingClass.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/condition/ConditionalOnProperty.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/context/ConfigurationPropertiesAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/context/LifecycleAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration$GitResourceAvailableCondition.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/jmx/JmxAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/ssl/SslAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$AsyncConfigurerConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$AsyncConfigurerWrapperConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$BootstrapExecutorConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$OnExecutorCondition$ExecutorBeanCondition.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$OnExecutorCondition$ModelCondition.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$OnExecutorCondition.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$SimpleAsyncTaskExecutorBuilderConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$TaskExecutorConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskExecutorConfigurations$ThreadPoolTaskExecutorBuilderConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskSchedulingConfigurations$SimpleAsyncTaskSchedulerBuilderConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskSchedulingConfigurations$TaskSchedulerConfiguration.class" + }, { + "glob" : "org/springframework/boot/autoconfigure/task/TaskSchedulingConfigurations$ThreadPoolTaskSchedulerBuilderConfiguration.class" + }, { + "glob" : "org/springframework/boot/context/properties/ConfigurationProperties.class" + }, { + "glob" : "org/springframework/boot/context/properties/EnableConfigurationProperties.class" + }, { + "glob" : "org/springframework/boot/context/properties/EnableConfigurationPropertiesRegistrar.class" + }, { + "glob" : "org/springframework/context/ApplicationListener.class" + }, { + "glob" : "org/springframework/context/annotation/AdviceModeImportSelector.class" + }, { + "glob" : "org/springframework/context/annotation/ComponentScan.class" + }, { + "glob" : "org/springframework/context/annotation/Conditional.class" + }, { + "glob" : "org/springframework/context/annotation/Configuration.class" + }, { + "glob" : "org/springframework/context/annotation/Import.class" + }, { + "glob" : "org/springframework/context/annotation/ImportAware.class" + }, { + "glob" : "org/springframework/context/annotation/ImportBeanDefinitionRegistrar.class" + }, { + "glob" : "org/springframework/context/annotation/Role.class" + }, { + "glob" : "org/springframework/core/Ordered.class" + }, { + "glob" : "org/springframework/scheduling/annotation/AbstractAsyncConfiguration.class" + }, { + "glob" : "org/springframework/scheduling/annotation/AsyncConfigurationSelector.class" + }, { + "glob" : "org/springframework/scheduling/annotation/EnableAsync.class" + }, { + "glob" : "org/springframework/scheduling/annotation/ProxyAsyncConfiguration.class" + }, { + "glob" : "org/springframework/web/bind/annotation/ControllerAdvice.class" + }, { + "glob" : "org/springframework/web/bind/annotation/Mapping.class" + }, { + "glob" : "org/springframework/web/bind/annotation/RequestMapping.class" + }, { + "glob" : "org/springframework/web/bind/annotation/ResponseBody.class" + }, { + "glob" : "org/springframework/web/bind/annotation/RestController.class" + }, { + "glob" : "reference.conf" + }, { + "glob" : "registry" + }, { + "glob" : "registry.conf" + }, { + "glob" : "registry.properties" + }, { + "glob" : "registry.yml" + }, { + "glob" : "spring.properties" + }, { + "module" : "jdk.jfr", + "glob" : "jdk/jfr/internal/types/metadata.bin" + }, { + "glob" : "META-INF/native/libnetty_transport_native_epoll_aarch_64.so" + }, { + "glob" : "META-INF/native/libnetty_transport_native_epoll_x86_64.so" + }, { + "glob" : "META-INF/seata/io.seata.config.ConfigurationProvider" + }, { + "glob" : "META-INF/seata/org.apache.seata.config.ConfigurationProvider" + }, { + "glob" : "META-INF/services/com.alibaba.nacos.api.config.filter.IConfigFilter" + }, { + "glob" : "META-INF/services/com.alibaba.nacos.api.remote.Payload" + }, { + "glob" : "META-INF/services/com.alibaba.nacos.common.notify.EventPublisher" + }, { + "glob" : "META-INF/services/com.alibaba.nacos.shaded.io.grpc.LoadBalancerProvider" + }, { + "glob" : "META-INF/services/com.alibaba.nacos.shaded.io.grpc.ManagedChannelProvider" + }, { + "glob" : "META-INF/services/com.alibaba.nacos.shaded.io.grpc.NameResolverProvider" + }, { + "glob" : "META-INF/services/io.seata.config.ConfigurationProvider" + }, { + "glob" : "META-INF/services/java.net.spi.InetAddressResolverProvider" + }, { + "glob" : "META-INF/services/org.apache.seata.config.ConfigurationProvider" + }, { + "glob" : "com/alibaba/nacos/api/config/remote/request" + }, { + "glob" : "com/alibaba/nacos/api/config/remote/response" + }, { + "glob" : "com/alibaba/nacos/api/naming/remote/request" + }, { + "glob" : "com/alibaba/nacos/api/naming/remote/response" + }, { + "glob" : "com/alibaba/nacos/api/remote/request" + }, { + "glob" : "com/alibaba/nacos/api/remote/response" + }, { + "glob" : "com/alibaba/nacos/naming/cluster/remote/request" + }, { + "glob" : "com/alibaba/nacos/naming/cluster/remote/response" + }, { + "glob" : "nacos-logback.xml" + }, { + "glob" : "nacos-version.txt" + }, { + "glob" : "spas.properties" + }, { + "glob" : "META-INF/native/libcom_alibaba_nacos_shaded_io_grpc_netty_shaded_netty_transport_native_epoll.so" + }, { + "glob" : "META-INF/native/libcom_alibaba_nacos_shaded_io_grpc_netty_shaded_netty_transport_native_epoll_x86_64.so" + }, { + "glob" : "META-INF/native/libcom_alibaba_nacos_shaded_io_grpc_netty_shaded_netty_transport_native_epoll_aarch_64.so" + }, { + "glob" : "META-INF/seata/org.apache.seata.common.json.JsonCodec" + }, { + "glob" : "META-INF/seata/org.apache.seata.common.json.JsonSerializer" + }, { + "glob" : "META-INF/services/org.apache.seata.common.json.JsonCodec" + }, { + "glob" : "META-INF/services/org.apache.seata.common.json.JsonSerializer" + }, { + "glob" : "fastjson.properties" + }, { + "module" : "java.base", + "glob" : "jdk/internal/icu/impl/data/icudt76b/nfkc.nrm" + }, { + "module" : "java.base", + "glob" : "jdk/internal/icu/impl/data/icudt76b/uprops.icu" + }, { + "module" : "java.base", + "glob" : "sun/net/idn/uidna.spp" + }, { + "module" : "java.base", + "glob" : "jdk/internal/icu/impl/data/icudt76b/nfc.nrm" + } ], + "foreign" : { + "downcalls" : [ { + "returnType" : "jlong", + "parameterTypes" : [ "jlong" ] + }, { + "returnType" : "void", + "parameterTypes" : [ "jlong" ] + } ] + } +} \ No newline at end of file diff --git a/server/src/main/resources/META-INF/spring.factories b/server/src/main/resources/META-INF/spring.factories index c0dd6f405e8..315d3a4825b 100644 --- a/server/src/main/resources/META-INF/spring.factories +++ b/server/src/main/resources/META-INF/spring.factories @@ -14,6 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +org.springframework.context.ApplicationContextInitializer=\ +org.apache.seata.server.NacosPayloadRegistryInitializer org.springframework.context.ApplicationListener=\ org.apache.seata.server.spring.listener.ServerApplicationListener,\ org.apache.seata.server.spring.listener.HttpFilterInitListener diff --git a/server/src/main/resources/META-INF/spring/aot.factories b/server/src/main/resources/META-INF/spring/aot.factories new file mode 100644 index 00000000000..1d7d9245f65 --- /dev/null +++ b/server/src/main/resources/META-INF/spring/aot.factories @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +org.springframework.aot.hint.RuntimeHintsRegistrar=\ +org.apache.seata.server.ApolloNativeRuntimeHints,\ +org.apache.seata.server.SeataServerRuntimeHints diff --git a/server/src/main/resources/logback-spring-jvm.xml b/server/src/main/resources/logback-spring-jvm.xml new file mode 100644 index 00000000000..016cdfc7d44 --- /dev/null +++ b/server/src/main/resources/logback-spring-jvm.xml @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + 0 + 2048 + true + + + + + true + 0 + 2048 + true + + + + true + 0 + 1024 + true + + + + true + 0 + 1024 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/src/main/resources/logback-spring.xml b/server/src/main/resources/logback-spring.xml index a303251e67e..b04c4ee6d2a 100644 --- a/server/src/main/resources/logback-spring.xml +++ b/server/src/main/resources/logback-spring.xml @@ -17,6 +17,21 @@ limitations under the License. --> + + @@ -38,61 +53,15 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + @@ -133,26 +102,8 @@ - - - - - - - - - - - - - - - - - - - - + + diff --git a/server/src/test/java/org/apache/seata/server/logging/AppenderTest.java b/server/src/test/java/org/apache/seata/server/logging/AppenderTest.java index bf9a1a3fd2a..0b2c454e66c 100644 --- a/server/src/test/java/org/apache/seata/server/logging/AppenderTest.java +++ b/server/src/test/java/org/apache/seata/server/logging/AppenderTest.java @@ -24,6 +24,7 @@ import org.apache.seata.server.BaseSpringBootTest; import org.apache.seata.server.logging.logback.appender.MetricLogbackAppender; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.slf4j.LoggerFactory; import org.springframework.test.context.TestPropertySource; @@ -31,6 +32,7 @@ import java.lang.reflect.Field; import java.util.Iterator; +@Disabled @TestPropertySource( properties = { "logging.extend.logstash-appender.enabled=true", diff --git a/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java b/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java index 349da18540f..cdfbfcefd48 100644 --- a/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java +++ b/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/provider/SpringBootConfigurationProvider.java @@ -25,12 +25,12 @@ import org.apache.seata.config.ExtConfigurationProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.cglib.proxy.Enhancer; -import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.lang.Nullable; import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; import java.time.Duration; import java.util.Map; import java.util.Objects; @@ -57,8 +57,10 @@ public class SpringBootConfigurationProvider implements ExtConfigurationProvider @Override public Configuration provide(Configuration originalConfiguration) { - return (Configuration) Enhancer.create( - originalConfiguration.getClass(), (MethodInterceptor) (proxy, method, args, methodProxy) -> { + return (Configuration) Proxy.newProxyInstance( + Configuration.class.getClassLoader(), + new Class[] {Configuration.class}, + (InvocationHandler) (proxy, method, args) -> { if (method.getName().startsWith(INTERCEPT_METHOD_PREFIX) && args.length > 0) { Object result; String rawDataId = (String) args[0]; diff --git a/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/server/session/SessionProperties.java b/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/server/session/SessionProperties.java index d4cfaae6da8..f99f9120164 100644 --- a/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/server/session/SessionProperties.java +++ b/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/server/session/SessionProperties.java @@ -49,11 +49,11 @@ public SessionProperties setBranchAsyncQueueSize(Integer branchAsyncQueueSize) { return this; } - public Boolean getEnableBranchAsync() { + public Boolean getEnableBranchAsyncRemove() { return enableBranchAsyncRemove; } - public SessionProperties setEnableBranchAsync(Boolean enableBranchAsyncRemove) { + public SessionProperties setEnableBranchAsyncRemove(Boolean enableBranchAsyncRemove) { this.enableBranchAsyncRemove = enableBranchAsyncRemove; return this; } diff --git a/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/server/session/SessionPropertiesTest.java b/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/server/session/SessionPropertiesTest.java index 0391461ffda..d6c596b2944 100644 --- a/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/server/session/SessionPropertiesTest.java +++ b/spring/seata-spring-autoconfigure/seata-spring-autoconfigure-server/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/server/session/SessionPropertiesTest.java @@ -24,10 +24,10 @@ public class SessionPropertiesTest { @Test public void testSessionProperties() { SessionProperties sessionProperties = new SessionProperties(); - sessionProperties.setEnableBranchAsync(true); + sessionProperties.setEnableBranchAsyncRemove(true); sessionProperties.setBranchAsyncQueueSize(1); - Assertions.assertTrue(sessionProperties.getEnableBranchAsync()); + Assertions.assertTrue(sessionProperties.getEnableBranchAsyncRemove()); Assertions.assertEquals(1, sessionProperties.getBranchAsyncQueueSize()); } } diff --git a/test-suite/test-native-metadata-merge/src/main/java/org/apache/seata/metadata/MergeNativeImageMetadata.java b/test-suite/test-native-metadata-merge/src/main/java/org/apache/seata/metadata/MergeNativeImageMetadata.java index 3681cfc5a49..3be3fb35e52 100644 --- a/test-suite/test-native-metadata-merge/src/main/java/org/apache/seata/metadata/MergeNativeImageMetadata.java +++ b/test-suite/test-native-metadata-merge/src/main/java/org/apache/seata/metadata/MergeNativeImageMetadata.java @@ -23,6 +23,7 @@ import java.util.LinkedHashMap; import java.util.Map; +import java.util.regex.Pattern; /** * Utility for merging GraalVM native image reachability metadata JSON files. @@ -138,9 +139,18 @@ private static void mergeArrayNodes(JsonNode sourceArray, ArrayNode targetArray) if (!containsNode(targetArray, sourceElement)) { targetArray.add(sourceElement); } - } else { - // Object without a recognizable key — always append as new entry. + } else if (sourceKey != null) { + // Object with a key not yet in target — append and register + // the key so subsequent source elements with the same key + // merge into this one instead of being appended as duplicates. targetArray.add(sourceElement); + targetIndex.put(sourceKey, targetArray.size() - 1); + } else { + // Object without a recognizable key — append only if not + // already present to avoid duplication. + if (!containsNode(targetArray, sourceElement)) { + targetArray.add(sourceElement); + } } } } @@ -190,7 +200,7 @@ private static String getElementKey(JsonNode element) { // ({"lambda": {...}}). Use toString() for non-textual values. if (element.has("type")) { StringBuilder sb = new StringBuilder("type:"); - sb.append(nodeText(element.get("type"))); + sb.append(normalizeType(nodeText(element.get("type")))); if (element.has("condition")) { sb.append("|condition:"); sb.append(nodeText(element.get("condition"))); @@ -237,4 +247,33 @@ private static String nodeText(JsonNode node) { } return node.toString(); } + + /** + * Pattern matching Guice-generated {@code FastClass} type names with a + * variable numeric hash suffix, e.g. + * {@code com.example.MyClass$$FastClassByGuice$$1231617}. + * + *

The numeric component is a hash derived from the base class method + * signatures; it can change between builds. Stripping it during key + * computation prevents duplicate entries from accumulating in the + * canonical metadata file. + */ + private static final Pattern FAST_CLASS_BY_GUICE_SUFFIX = Pattern.compile("\\$\\$FastClassByGuice\\$\\$\\d+$"); + + /** + * Normalizes a reflection type name for stable identity-key matching by + * stripping the variable numeric suffix from Guice FastClass names. + * + *

Example: + * {@code com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory$$FastClassByGuice$$1231617} + * → {@code com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory$$FastClassByGuice$$} + * + *

Type names that do not match the pattern are returned unchanged. + * + * @param typeValue the raw type name from a metadata entry + * @return the normalized type name for key matching + */ + static String normalizeType(String typeValue) { + return FAST_CLASS_BY_GUICE_SUFFIX.matcher(typeValue).replaceAll("\\$\\$FastClassByGuice\\$\\$"); + } } diff --git a/test-suite/test-native-metadata-merge/src/test/java/org/apache/seata/metadata/ExecuteMergeNativeImageMetadataTests.java b/test-suite/test-native-metadata-merge/src/test/java/org/apache/seata/metadata/ExecuteMergeNativeImageMetadataTests.java index 678607d499e..12cbc747b7b 100644 --- a/test-suite/test-native-metadata-merge/src/test/java/org/apache/seata/metadata/ExecuteMergeNativeImageMetadataTests.java +++ b/test-suite/test-native-metadata-merge/src/test/java/org/apache/seata/metadata/ExecuteMergeNativeImageMetadataTests.java @@ -81,4 +81,36 @@ void namingServer() { // Write back the merged result with pretty printing objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File(target), targetNode); } + + /** + * Merges the server's generated reachability metadata into its + * canonical native image metadata file. + * + *

Source: {@code target/native-image-config/reachability-metadata.json} + * (generated by the native image agent during build). + * + *

Target: {@code server/src/main/resources/META-INF/native-image/reachability-metadata.json} + * (versioned alongside the source code). + * + *

Only runs when the environment variable + * {@code EXECUTE_NATIVE_METADATA_MERGE_SERVER=true} is set. + */ + @Test + @EnabledIfEnvironmentVariable(named = "EXECUTE_NATIVE_METADATA_MERGE_SERVER", matches = "true") + void server() { + + // Generated metadata from the build output directory + String source = PROJECT_BASE + "/target/native-image-config/reachability-metadata.json"; + // Canonical metadata file in the server source tree + String target = PROJECT_BASE + "/server/src/main/resources/META-INF/native-image/reachability-metadata.json"; + + JsonNode sourceNode = objectMapper.readTree(new File(source)); + JsonNode targetNode = objectMapper.readTree(new File(target)); + + // Merge generated entries into the canonical file + MergeNativeImageMetadata.mergeObjectNodes(sourceNode, targetNode); + + // Write back the merged result with pretty printing + objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File(target), targetNode); + } } diff --git a/test-suite/test-native-metadata-merge/src/test/java/org/apache/seata/metadata/MergeNativeImageMetadataTests.java b/test-suite/test-native-metadata-merge/src/test/java/org/apache/seata/metadata/MergeNativeImageMetadataTests.java index 23856c7130d..16b3a6da4d1 100644 --- a/test-suite/test-native-metadata-merge/src/test/java/org/apache/seata/metadata/MergeNativeImageMetadataTests.java +++ b/test-suite/test-native-metadata-merge/src/test/java/org/apache/seata/metadata/MergeNativeImageMetadataTests.java @@ -340,4 +340,98 @@ void addReflectionTypeFields() { assertEquals(sourceNode, targetNode); } + + /** + * When source contains a {@code FastClassByGuice} entry with a + * different numeric suffix than the target, the entries should be + * recognized as the same logical element (no duplicate created) + * and the target's original {@code type} value should be preserved + * to avoid meaningless metadata churn. + */ + @Test + void deduplicateFastClassByGuiceDifferentSuffixes() { + + String source = + """ + { + "reflection" : [ { + "type" : "com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory$$FastClassByGuice$$9999999", + "fields" : [ { + "name" : "GUICE$INVOKERS" + } ] + } ] + } + """; + String target = + """ + { + "reflection" : [ { + "type" : "com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory$$FastClassByGuice$$1111111", + "fields" : [ { + "name" : "GUICE$INVOKERS" + } ] + } ] + } + """; + + JsonNode sourceNode = objectMapper.readTree(source); + JsonNode targetNode = objectMapper.readTree(target); + + MergeNativeImageMetadata.mergeObjectNodes(sourceNode, targetNode); + + // Target should still have exactly one reflection entry — no duplicate. + assertEquals(1, targetNode.get("reflection").size(), "Should have exactly one entry after merge"); + // The type field should keep the target's original value — the numeric + // suffix is a transient hash that doesn't meaningfully change behavior. + assertEquals( + "com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory$$FastClassByGuice$$1111111", + targetNode.get("reflection").get(0).get("type").asString(), + "Type should preserve target's original value"); + } + + /** + * Verifies that Spring CGLIB entries with fixed numeric suffixes + * ({@code $$0}, {@code $$1}) are NOT affected by the FastClassByGuice + * normalization — they are distinct CGLIB proxies. + */ + @Test + void doesNotAffectSpringCglibEntries() { + + String source = + """ + { + "reflection" : [ { + "type" : "org.apache.seata.server.config.ServerConfig$$SpringCGLIB$$FastClass$$0", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Class" ] + } ] + } ] + } + """; + String target = + """ + { + "reflection" : [ { + "type" : "org.apache.seata.server.config.ServerConfig$$SpringCGLIB$$FastClass$$1", + "methods" : [ { + "name" : "", + "parameterTypes" : [ "java.lang.Class" ] + } ] + } ] + } + """; + + JsonNode sourceNode = objectMapper.readTree(source); + JsonNode targetNode = objectMapper.readTree(target); + + MergeNativeImageMetadata.mergeObjectNodes(sourceNode, targetNode); + + // Both entries should remain — $$FastClass$$0 and $$FastClass$$1 are + // distinct CGLIB proxy classes, not transient duplicates. + assertEquals( + 2, + targetNode.get("reflection").size(), + "SpringCGLIB entries with different fixed suffixes should remain distinct"); + } } diff --git a/test-suite/test-native-server/pom.xml b/test-suite/test-native-server/pom.xml new file mode 100644 index 00000000000..81b7a50a884 --- /dev/null +++ b/test-suite/test-native-server/pom.xml @@ -0,0 +1,118 @@ + + + + 4.0.0 + + org.apache.seata + seata-parent + ${revision} + ../../pom.xml + + seata-test-native-server + ${project.artifactId} ${project.version} + + + + + + + + + + + + + + + + 17 + 4.0.6 + 4.13.2 + + + + + org.apache.seata + seata-spring-boot-starter + ${project.version} + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-webmvc + + + + com.mysql + mysql-connector-j + runtime + + + org.springframework.boot + spring-boot-starter-actuator-test + test + + + org.springframework.boot + spring-boot-starter-data-jpa-test + test + + + org.springframework.boot + spring-boot-starter-webmvc-test + test + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + org.antlr + antlr4-runtime + ${antlr4.version} + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + + diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/SeataTestNativeApplication.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/SeataTestNativeApplication.java new file mode 100644 index 00000000000..b618a33151a --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/SeataTestNativeApplication.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.seata.server; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SeataTestNativeApplication { + + public static void main(String[] args) { + SpringApplication.run(SeataTestNativeApplication.class, args); + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/config/ControllerAdviceConfig.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/config/ControllerAdviceConfig.java new file mode 100644 index 00000000000..00906f92fa6 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/config/ControllerAdviceConfig.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.seata.server.config; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import java.util.Map; + +@ControllerAdvice({"org.apache.seata"}) +public class ControllerAdviceConfig { + + /** + * Set HTTP response status code to 500 for distributed transaction rollback + */ + @ResponseBody + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ExceptionHandler(Exception.class) + public Map exception( + HttpServletRequest request, HttpServletResponse response, Exception exception) { + String message = exception.getMessage(); + return Map.of("status", 500, "error", message); + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/config/EarlyDatabaseInitializer.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/config/EarlyDatabaseInitializer.java new file mode 100644 index 00000000000..95489882fc1 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/config/EarlyDatabaseInitializer.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.seata.server.config; + +import com.zaxxer.hikari.HikariDataSource; +import org.jspecify.annotations.NullMarked; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.EnvironmentAware; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ClassPathResource; +import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils; +import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; + +/** + * Execute schema.sql and data.sql early, before any Spring beans are instantiated. + *

+ * This is needed because Seata's {@code DataSourceProxy} checks for the + * {@code undo_log} table during {@code BeanPostProcessor} processing — before + * Spring Boot's {@code DataSourceScriptDatabaseInitializer} (which normally + * runs schema.sql) gets a chance to execute. By running the DDL/DML scripts + * in a {@link BeanFactoryPostProcessor}, we guarantee the tables exist before + * the DataSource bean is created and wrapped by Seata. + */ +@Configuration +public class EarlyDatabaseInitializer implements BeanFactoryPostProcessor, EnvironmentAware { + + private static final Logger LOGGER = LoggerFactory.getLogger(EarlyDatabaseInitializer.class); + + private Environment environment; + + @NullMarked + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @NullMarked + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + String url = environment.getProperty("spring.datasource.url"); + String username = environment.getProperty("spring.datasource.username"); + String password = environment.getProperty("spring.datasource.password"); + String driverClassName = environment.getProperty("spring.datasource.driver-class-name"); + + if (url == null) { + LOGGER.warn("spring.datasource.url is not set, skipping early database initialization"); + return; + } + + LOGGER.info("Initializing database schema and data early (before Seata DataSource proxy)..."); + + try (HikariDataSource tempDataSource = new HikariDataSource()) { + tempDataSource.setJdbcUrl(url); + if (username != null) { + tempDataSource.setUsername(username); + } + if (password != null) { + tempDataSource.setPassword(password); + } + if (driverClassName != null) { + tempDataSource.setDriverClassName(driverClassName); + } + tempDataSource.setMaximumPoolSize(2); + tempDataSource.setPoolName("EarlyDbInit"); + + ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); + populator.addScript(new ClassPathResource("schema.sql")); + populator.addScript(new ClassPathResource("data.sql")); + populator.setContinueOnError(false); + DatabasePopulatorUtils.execute(populator, tempDataSource); + LOGGER.info("Early database initialization completed successfully."); + } + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/AccountRestController.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/AccountRestController.java new file mode 100644 index 00000000000..ed6815e4e11 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/AccountRestController.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.seata.server.controller; + +import org.apache.seata.core.context.RootContext; +import org.apache.seata.server.dto.AccountMoneyRequest; +import org.apache.seata.server.service.AccountService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("/account") +public class AccountRestController { + + private static final Logger LOGGER = LoggerFactory.getLogger(AccountRestController.class); + + private AccountService accountService; + + @Autowired + public void setAccountService(AccountService accountService) { + this.accountService = accountService; + } + + /** + * Modify user balance + * + * @param request request parameters + * @param keyXid distributed transaction ID + */ + @PostMapping("/money") + public Map money( + @RequestBody AccountMoneyRequest request, + @RequestHeader(value = RootContext.KEY_XID, required = false) String keyXid) { + LOGGER.info("Distributed transaction {}: {}", RootContext.KEY_XID, keyXid); + + accountService.money(request); + return Map.of("code", 200); + } + + @GetMapping("/money/{userId}") + public long money(@PathVariable String userId) { + return accountService.getMoney(userId); + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/HealthRestController.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/HealthRestController.java new file mode 100644 index 00000000000..6fdb1d6f6cb --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/HealthRestController.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.seata.server.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HealthRestController { + + @RequestMapping("/health") + public String health() { + return "ok"; + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/OrderRestController.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/OrderRestController.java new file mode 100644 index 00000000000..c516518722f --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/OrderRestController.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.seata.server.controller; + +import org.apache.seata.core.context.RootContext; +import org.apache.seata.server.dto.OrderRequest; +import org.apache.seata.server.service.OrderService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("/order") +public class OrderRestController { + private static final Logger LOGGER = LoggerFactory.getLogger(OrderRestController.class); + + private OrderService orderService; + + @Autowired + public void setOrderService(OrderService orderService) { + this.orderService = orderService; + } + + /** + * Create order + * + * @param request request parameters + * @param keyXid distributed transaction ID + */ + @PostMapping + public Map order( + @RequestBody OrderRequest request, + @RequestHeader(value = RootContext.KEY_XID, required = false) String keyXid) { + LOGGER.info("Distributed transaction {}: {}", RootContext.KEY_XID, keyXid); + + orderService.order(request); + return Map.of("code", 200); + } + + @GetMapping("/{commodityCode}") + public long count(@PathVariable String commodityCode) { + return orderService.count(commodityCode); + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/SeataRestController.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/SeataRestController.java new file mode 100644 index 00000000000..f255c353551 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/SeataRestController.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.server.controller; + +import org.apache.seata.core.context.RootContext; +import org.apache.seata.server.dto.AccountMoneyRequest; +import org.apache.seata.server.dto.OrderRequest; +import org.apache.seata.server.dto.SeataRequest; +import org.apache.seata.server.dto.StorageRequest; +import org.apache.seata.spring.annotation.GlobalTransactional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.server.autoconfigure.ServerProperties; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +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.RestController; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; + +@RestController +@RequestMapping("/seata") +public class SeataRestController { + + private static final Logger LOGGER = LoggerFactory.getLogger(SeataRestController.class); + + private static final RestTemplate REST_TEMPLATE = new RestTemplate(); + + private ServerProperties serverProperties; + + @Autowired + public void setServerProperties(ServerProperties serverProperties) { + this.serverProperties = serverProperties; + } + + /** + * Test distributed transaction + * + * @param request request parameters + */ + @GlobalTransactional + @PostMapping + public Map seata(@RequestBody SeataRequest request) { + + String xid = RootContext.getXID(); + LOGGER.info("Distributed transaction {}: {}", RootContext.KEY_XID, xid); + if (xid == null) { + throw new NullPointerException("xid is null"); + } + + Integer port = serverProperties.getPort(); + if (port == null) { + port = 8080; + } + + // Deduct balance + { + String url = "http://127.0.0.1:" + port + "/account/money"; + + AccountMoneyRequest accountMoneyRequest = new AccountMoneyRequest(); + accountMoneyRequest.setUserId(request.getUserId()); + accountMoneyRequest.setMoney(request.getMoney()); + + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.set(RootContext.KEY_XID, xid); + HttpEntity httpEntity = new HttpEntity<>(accountMoneyRequest, httpHeaders); + + Map map = REST_TEMPLATE.postForObject(url, httpEntity, Map.class); + LOGGER.info("Balance deduction result: {}", map); + } + + // Deduct stock + { + String url = "http://127.0.0.1:" + port + "/storage"; + + StorageRequest storageRequest = new StorageRequest(); + storageRequest.setCommodityCode(request.getCommodityCode()); + storageRequest.setCount(request.getCount()); + + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.set(RootContext.KEY_XID, xid); + HttpEntity httpEntity = new HttpEntity<>(storageRequest, httpHeaders); + + Map map = REST_TEMPLATE.postForObject(url, httpEntity, Map.class); + LOGGER.info("Stock deduction result: {}", map); + } + + // Create order + { + String url = "http://127.0.0.1:" + port + "/order"; + + OrderRequest orderRequest = new OrderRequest(); + orderRequest.setUserId(request.getUserId()); + orderRequest.setCommodityCode(request.getCommodityCode()); + orderRequest.setCount(request.getCount()); + orderRequest.setMoney(request.getMoney()); + + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.set(RootContext.KEY_XID, xid); + HttpEntity httpEntity = new HttpEntity<>(orderRequest, httpHeaders); + + Map map = REST_TEMPLATE.postForObject(url, httpEntity, Map.class); + LOGGER.info("Order creation result: {}", map); + } + + return Map.of("code", 200); + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/StorageRestController.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/StorageRestController.java new file mode 100644 index 00000000000..a66b21ee042 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/controller/StorageRestController.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.seata.server.controller; + +import org.apache.seata.core.context.RootContext; +import org.apache.seata.server.dto.StorageRequest; +import org.apache.seata.server.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("/storage") +public class StorageRestController { + + private static final Logger LOGGER = LoggerFactory.getLogger(StorageRestController.class); + + private final StorageService storageService; + + public StorageRestController(StorageService storageService) { + this.storageService = storageService; + } + + /** + * Modify stock quantity + * @param request request parameters + * @param keyXid distributed transaction ID + * @return + */ + @PostMapping + public Map storage( + @RequestBody StorageRequest request, + @RequestHeader(value = RootContext.KEY_XID, required = false) String keyXid) { + LOGGER.info("Distributed transaction {}: {}", RootContext.KEY_XID, keyXid); + + storageService.storage(request); + return Map.of("code", 200); + } + + @GetMapping("/{commodityCode}") + public long count(@PathVariable String commodityCode) { + return storageService.count(commodityCode); + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/AccountDAO.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/AccountDAO.java new file mode 100644 index 00000000000..b102f051860 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/AccountDAO.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.seata.server.dao; + +import org.apache.seata.server.entity.Account; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface AccountDAO extends JpaRepository { + + Account findByUserId(String userId); +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/OrderDAO.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/OrderDAO.java new file mode 100644 index 00000000000..3724acf2e8b --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/OrderDAO.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.seata.server.dao; + +import org.apache.seata.server.entity.Order; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface OrderDAO extends JpaRepository { + int countByCommodityCode(String commodityCode); +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/StorageDAO.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/StorageDAO.java new file mode 100644 index 00000000000..f0fca412290 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/StorageDAO.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.seata.server.dao; + +import org.apache.seata.server.entity.Storage; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface StorageDAO extends JpaRepository { + + Storage findByCommodityCode(String commodityCode); +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/UndoLogDAO.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/UndoLogDAO.java new file mode 100644 index 00000000000..d3daabe8ace --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dao/UndoLogDAO.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.seata.server.dao; + +import org.apache.seata.server.entity.UndoLog; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface UndoLogDAO extends JpaRepository {} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/AccountMoneyRequest.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/AccountMoneyRequest.java new file mode 100644 index 00000000000..a1315ff9a6f --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/AccountMoneyRequest.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.seata.server.dto; + +/** + * Account balance modification request parameters + * + */ +public class AccountMoneyRequest { + + /** + * User ID + */ + private String userId; + + /** + * Amount: positive value to increase, negative value to decrease, throws exception when insufficient + */ + private Long money; + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public Long getMoney() { + return money; + } + + public void setMoney(Long money) { + this.money = money; + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/OrderRequest.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/OrderRequest.java new file mode 100644 index 00000000000..6d3595af1d0 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/OrderRequest.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.seata.server.dto; + +/** + * Order creation request parameters + * + */ +public class OrderRequest { + + /** + * User ID + */ + private String userId; + + /** + * Commodity code + */ + private String commodityCode; + + /** + * Total count + */ + private Long count; + + /** + * Total amount + */ + private Long money; + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getCommodityCode() { + return commodityCode; + } + + public void setCommodityCode(String commodityCode) { + this.commodityCode = commodityCode; + } + + public Long getCount() { + return count; + } + + public void setCount(Long count) { + this.count = count; + } + + public Long getMoney() { + return money; + } + + public void setMoney(Long money) { + this.money = money; + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/SeataRequest.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/SeataRequest.java new file mode 100644 index 00000000000..3f63cce80d9 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/SeataRequest.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.seata.server.dto; + +/** + * Seata distributed transaction request parameters + * + */ +public class SeataRequest { + + /** + * Commodity code + */ + private String commodityCode; + + /** + * User ID + */ + private String userId; + + /** + * Total count + */ + private Long count; + + /** + * Total amount + */ + private Long money; + + public String getCommodityCode() { + return commodityCode; + } + + public void setCommodityCode(String commodityCode) { + this.commodityCode = commodityCode; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public Long getCount() { + return count; + } + + public void setCount(Long count) { + this.count = count; + } + + public Long getMoney() { + return money; + } + + public void setMoney(Long money) { + this.money = money; + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/StorageRequest.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/StorageRequest.java new file mode 100644 index 00000000000..92d41cf0661 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/dto/StorageRequest.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.seata.server.dto; + +/** + * Stock modification request parameters + * + */ +public class StorageRequest { + + /** + * Commodity code + */ + private String commodityCode; + + /** + * Quantity: positive value to increase, negative value to decrease, throws exception when insufficient + */ + private Long count; + + public String getCommodityCode() { + return commodityCode; + } + + public void setCommodityCode(String commodityCode) { + this.commodityCode = commodityCode; + } + + public Long getCount() { + return count; + } + + public void setCount(Long count) { + this.count = count; + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/Account.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/Account.java new file mode 100644 index 00000000000..6c81551a5c9 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/Account.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.seata.server.entity; + +import jakarta.persistence.*; + +@Entity +@Table(name = "account_tbl") +public class Account { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(name = "user_id") + private String userId; + + @Column(columnDefinition = "INT DEFAULT 0") + private Long money; + + // Constructors + + public Account() {} + + public Account(String userId, Long money) { + this.userId = userId; + this.money = money; + } + + // Getters and Setters + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public Long getMoney() { + return money; + } + + public void setMoney(Long money) { + this.money = money; + } + + @Override + public String toString() { + return "Account{" + "id=" + id + ", userId='" + userId + '\'' + ", money=" + money + '}'; + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/Order.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/Order.java new file mode 100644 index 00000000000..3c834a9cc7c --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/Order.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.seata.server.entity; + +import jakarta.persistence.*; + +@Entity +@Table(name = "order_tbl") +public class Order { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(name = "user_id") + private String userId; + + @Column(name = "commodity_code") + private String commodityCode; + + @Column(columnDefinition = "INT DEFAULT 0") + private Integer count; + + @Column(columnDefinition = "INT DEFAULT 0") + private Integer money; + + // Constructors + + public Order() {} + + public Order(String userId, String commodityCode, Integer count, Integer money) { + this.userId = userId; + this.commodityCode = commodityCode; + this.count = count; + this.money = money; + } + + // Getters and Setters + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getCommodityCode() { + return commodityCode; + } + + public void setCommodityCode(String commodityCode) { + this.commodityCode = commodityCode; + } + + public Integer getCount() { + return count; + } + + public void setCount(Integer count) { + this.count = count; + } + + public Integer getMoney() { + return money; + } + + public void setMoney(Integer money) { + this.money = money; + } + + @Override + public String toString() { + return "Order{" + "id=" + + id + ", userId='" + + userId + '\'' + ", commodityCode='" + + commodityCode + '\'' + ", count=" + + count + ", money=" + + money + '}'; + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/Storage.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/Storage.java new file mode 100644 index 00000000000..af5f0dae00a --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/Storage.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.seata.server.entity; + +import jakarta.persistence.*; + +@Entity +@Table(name = "storage_tbl", uniqueConstraints = @UniqueConstraint(columnNames = "commodity_code")) +public class Storage { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Column(name = "commodity_code") + private String commodityCode; + + @Column(columnDefinition = "INT DEFAULT 0") + private Long count; + + // Constructors + + public Storage() {} + + public Storage(String commodityCode, Long count) { + this.commodityCode = commodityCode; + this.count = count; + } + + // Getters and Setters + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getCommodityCode() { + return commodityCode; + } + + public void setCommodityCode(String commodityCode) { + this.commodityCode = commodityCode; + } + + public Long getCount() { + return count; + } + + public void setCount(Long count) { + this.count = count; + } + + @Override + public String toString() { + return "Storage{" + "id=" + id + ", commodityCode='" + commodityCode + '\'' + ", count=" + count + '}'; + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/UndoLog.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/UndoLog.java new file mode 100644 index 00000000000..a2747daf099 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/entity/UndoLog.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.server.entity; + +import jakarta.persistence.*; + +import java.time.LocalDateTime; + +@Entity +@Table( + name = "undo_log", + uniqueConstraints = + @UniqueConstraint( + name = "ux_undo_log", + columnNames = {"xid", "branch_id"})) +public class UndoLog { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "branch_id", nullable = false) + private Long branchId; + + @Column(nullable = false, length = 100) + private String xid; + + @Column(nullable = false, length = 128) + private String context; + + @Lob + @Column(name = "rollback_info", nullable = false, columnDefinition = "LONGBLOB") + private byte[] rollbackInfo; + + @Column(name = "log_status", nullable = false) + private Integer logStatus; + + @Column(name = "log_created", nullable = false) + private LocalDateTime logCreated; + + @Column(name = "log_modified", nullable = false) + private LocalDateTime logModified; + + @Column(length = 100) + private String ext; + + // Constructors + + public UndoLog() {} + + // Getters and Setters + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getBranchId() { + return branchId; + } + + public void setBranchId(Long branchId) { + this.branchId = branchId; + } + + public String getXid() { + return xid; + } + + public void setXid(String xid) { + this.xid = xid; + } + + public String getContext() { + return context; + } + + public void setContext(String context) { + this.context = context; + } + + public byte[] getRollbackInfo() { + return rollbackInfo; + } + + public void setRollbackInfo(byte[] rollbackInfo) { + this.rollbackInfo = rollbackInfo; + } + + public Integer getLogStatus() { + return logStatus; + } + + public void setLogStatus(Integer logStatus) { + this.logStatus = logStatus; + } + + public LocalDateTime getLogCreated() { + return logCreated; + } + + public void setLogCreated(LocalDateTime logCreated) { + this.logCreated = logCreated; + } + + public LocalDateTime getLogModified() { + return logModified; + } + + public void setLogModified(LocalDateTime logModified) { + this.logModified = logModified; + } + + public String getExt() { + return ext; + } + + public void setExt(String ext) { + this.ext = ext; + } + + @Override + public String toString() { + return "UndoLog{" + "id=" + + id + ", branchId=" + + branchId + ", xid='" + + xid + '\'' + ", logStatus=" + + logStatus + '}'; + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/AccountService.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/AccountService.java new file mode 100644 index 00000000000..44dc4a3d693 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/AccountService.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.seata.server.service; + +import org.apache.seata.server.dto.AccountMoneyRequest; + +public interface AccountService { + + Long getMoney(String userId); + + void money(AccountMoneyRequest request); +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/BusinessService.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/BusinessService.java new file mode 100644 index 00000000000..44c0cb099c6 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/BusinessService.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.seata.server.service; + +/** + * Business service for purchase operations + */ +public interface BusinessService {} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/OrderService.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/OrderService.java new file mode 100644 index 00000000000..21fe05b7eba --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/OrderService.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.seata.server.service; + +import org.apache.seata.server.dto.OrderRequest; + +public interface OrderService { + + long count(String commodityCode); + + void order(OrderRequest request); +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/StorageService.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/StorageService.java new file mode 100644 index 00000000000..c080b22c952 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/StorageService.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.seata.server.service; + +import org.apache.seata.server.dto.StorageRequest; + +public interface StorageService { + + Long count(String commodityCode); + + void storage(StorageRequest request); +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/AccountServiceImpl.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/AccountServiceImpl.java new file mode 100644 index 00000000000..7f76be18d6f --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/AccountServiceImpl.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.seata.server.service.impl; + +import org.apache.seata.server.dao.AccountDAO; +import org.apache.seata.server.dto.AccountMoneyRequest; +import org.apache.seata.server.entity.Account; +import org.apache.seata.server.service.AccountService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class AccountServiceImpl implements AccountService { + + private AccountDAO accountDAO; + + @Autowired + public void setAccountDAO(AccountDAO accountDAO) { + this.accountDAO = accountDAO; + } + + @Override + public Long getMoney(String userId) { + Account account = accountDAO.findByUserId(userId); + if (account == null) { + return null; + } + return account.getMoney(); + } + + @Override + @Transactional + public void money(AccountMoneyRequest request) { + String userId = request.getUserId(); + Long money = request.getMoney(); + + if (money == null) { + return; + } + + if (money == 0) { + return; + } + + Account account = accountDAO.findByUserId(userId); + if (account == null) { + throw new RuntimeException("User does not exist"); + } + + if (money > 0) { + account.setMoney(account.getMoney() + money); + } else { + if (account.getMoney() + money < 0) { + throw new RuntimeException("Insufficient balance"); + } + account.setMoney(account.getMoney() + money); + } + accountDAO.save(account); + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/BusinessServiceImpl.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/BusinessServiceImpl.java new file mode 100644 index 00000000000..8941a222c00 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/BusinessServiceImpl.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.seata.server.service.impl; + +import org.apache.seata.server.service.BusinessService; +import org.springframework.stereotype.Service; + +@Service +public class BusinessServiceImpl implements BusinessService {} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/OrderServiceImpl.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/OrderServiceImpl.java new file mode 100644 index 00000000000..a3909223003 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/OrderServiceImpl.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.seata.server.service.impl; + +import org.apache.seata.server.dao.OrderDAO; +import org.apache.seata.server.dto.OrderRequest; +import org.apache.seata.server.entity.Order; +import org.apache.seata.server.service.OrderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class OrderServiceImpl implements OrderService { + + private OrderDAO orderDAO; + + @Autowired + public void setOrderDAO(OrderDAO orderDAO) { + this.orderDAO = orderDAO; + } + + @Override + public long count(String commodityCode) { + return orderDAO.countByCommodityCode(commodityCode); + } + + @Override + @Transactional + public void order(OrderRequest request) { + Long count = request.getCount(); + Long money = request.getMoney(); + String commodityCode = request.getCommodityCode(); + String userId = request.getUserId(); + if (count == null) { + throw new RuntimeException("Order count must not be null"); + } + if (money == null) { + throw new RuntimeException("Order amount must not be null"); + } + count = Math.abs(count); + money = Math.abs(money); + Order order = new Order(userId, commodityCode, count.intValue(), money.intValue()); + orderDAO.save(order); + } +} diff --git a/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/StorageServiceImpl.java b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/StorageServiceImpl.java new file mode 100644 index 00000000000..b2191a9d589 --- /dev/null +++ b/test-suite/test-native-server/src/main/java/org/apache/seata/server/service/impl/StorageServiceImpl.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.seata.server.service.impl; + +import org.apache.seata.server.dao.StorageDAO; +import org.apache.seata.server.dto.StorageRequest; +import org.apache.seata.server.entity.Storage; +import org.apache.seata.server.service.StorageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class StorageServiceImpl implements StorageService { + + private StorageDAO storageDAO; + + @Autowired + public void setStorageDAO(StorageDAO storageDAO) { + this.storageDAO = storageDAO; + } + + @Override + public Long count(String commodityCode) { + Storage storage = storageDAO.findByCommodityCode(commodityCode); + if (storage == null) { + return null; + } + return storage.getCount(); + } + + @Override + @Transactional + public void storage(StorageRequest request) { + String commodityCode = request.getCommodityCode(); + Long count = request.getCount(); + if (count == null) { + return; + } + + if (count == 0) { + return; + } + Storage storage = storageDAO.findByCommodityCode(commodityCode); + if (storage == null) { + throw new RuntimeException("Commodity does not exist"); + } + if (count > 0) { + storage.setCount(storage.getCount() + count); + } else { + if (storage.getCount() + count < 0) { + throw new RuntimeException("Insufficient stock"); + } + storage.setCount(storage.getCount() + count); + } + storageDAO.save(storage); + } +} diff --git a/test-suite/test-native-server/src/main/resources/application.yaml b/test-suite/test-native-server/src/main/resources/application.yaml new file mode 100644 index 00000000000..432400118f8 --- /dev/null +++ b/test-suite/test-native-server/src/main/resources/application.yaml @@ -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. +# + +server: + port: 50180 + +--- + +spring: + application: + name: seata-test-native-server + +--- + +spring: + datasource: + driver-class-name: ${DATASOURCE_DRIVER:com.mysql.cj.jdbc.Driver} + url: ${DATASOURCE_URL:jdbc:mysql://127.0.0.1:3306/${DATASOURCE_DB:seata_test_native}?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC} + username: ${DATASOURCE_USERNAME:root} + password: ${DATASOURCE_PASSWORD:} + jpa: + hibernate: + ddl-auto: none + defer-datasource-initialization: false + show-sql: true + +--- + +spring: + sql: + init: + # Disabled because schema.sql and data.sql are executed early via + # EarlyDatabaseInitializer (a BeanFactoryPostProcessor) to ensure + # the undo_log table exists before Seata's DataSourceProxy checks for it. + mode: never + +--- + +seata: + config: + type: file + registry: + type: file + tx-service-group: default_tx_group + data-source-proxy-mode: AT + service: + vgroup-mapping: + default_tx_group: default + grouplist: + default: ${SEATA_SERVER_ADDR:127.0.0.1:8091} diff --git a/test-suite/test-native-server/src/main/resources/data.sql b/test-suite/test-native-server/src/main/resources/data.sql new file mode 100644 index 00000000000..a674d8c3ed5 --- /dev/null +++ b/test-suite/test-native-server/src/main/resources/data.sql @@ -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. +-- + +INSERT IGNORE INTO `storage_tbl` (`commodity_code`, `count`) VALUES ('A001', 200); +INSERT IGNORE INTO `account_tbl` (`user_id`, `money`) VALUES ('U001', 100); diff --git a/test-suite/test-native-server/src/main/resources/schema.sql b/test-suite/test-native-server/src/main/resources/schema.sql new file mode 100644 index 00000000000..a374104e147 --- /dev/null +++ b/test-suite/test-native-server/src/main/resources/schema.sql @@ -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. +-- + +DROP TABLE IF EXISTS `undo_log`; +CREATE TABLE `undo_log` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `branch_id` bigint(20) NOT NULL, + `xid` varchar(100) NOT NULL, + `context` varchar(128) NOT NULL, + `rollback_info` longblob NOT NULL, + `log_status` int(11) NOT NULL, + `log_created` datetime NOT NULL, + `log_modified` datetime NOT NULL, + `ext` varchar(100) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + + +DROP TABLE IF EXISTS `storage_tbl`; +CREATE TABLE `storage_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY (`commodity_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +DROP TABLE IF EXISTS `order_tbl`; +CREATE TABLE `order_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT 0, + `money` int(11) DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +DROP TABLE IF EXISTS `account_tbl`; +CREATE TABLE `account_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `money` int(11) DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/test-suite/test-native-server/src/test/java/org/apache/seata/server/controller/SeataRestControllerTests.java b/test-suite/test-native-server/src/test/java/org/apache/seata/server/controller/SeataRestControllerTests.java new file mode 100644 index 00000000000..1cfcbc36139 --- /dev/null +++ b/test-suite/test-native-server/src/test/java/org/apache/seata/server/controller/SeataRestControllerTests.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.seata.server.controller; + +import org.apache.seata.server.dto.SeataRequest; +import org.apache.seata.server.service.AccountService; +import org.apache.seata.server.service.OrderService; +import org.apache.seata.server.service.StorageService; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpEntity; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@SpringBootTest +class SeataRestControllerTests { + private static final Logger LOGGER = LoggerFactory.getLogger(SeataRestControllerTests.class); + + @Autowired + private AccountService accountService; + + @Autowired + private OrderService orderService; + + @Autowired + private StorageService storageService; + + @Test + void ok() { + String userId = "U001"; + String commodityCode = "A001"; + long count = -2; + long money = -1; + + Long money1 = accountService.getMoney(userId); + long orderCount1 = orderService.count(commodityCode); + long storageCount1 = storageService.count(commodityCode); + + { + SeataRequest request = new SeataRequest(); + request.setCommodityCode(commodityCode); + request.setUserId(userId); + request.setCount(count); + request.setMoney(money); + + HttpEntity httpEntity = new HttpEntity<>(request); + + String url = "http://127.0.0.1:50180/seata"; + String value = new RestTemplate().postForObject(url, httpEntity, String.class); + LOGGER.info(value); + assertEquals("{\"code\":200}", value); + } + + Long money2 = accountService.getMoney(userId); + long orderCount2 = orderService.count(commodityCode); + long storageCount2 = storageService.count(commodityCode); + + assertEquals(money1 + money, money2); + assertEquals(orderCount1 + 1, orderCount2); + assertEquals(storageCount1 + count, storageCount2); + } + + /** + * Test distributed transaction: data rollback + */ + @Test + void error() { + String userId = "U001"; + String commodityCode = "A001"; + + // First: balance deduction succeeds + long money = -1; + + // Second: stock deduction fails + long count = -20000000; + + Long money1 = accountService.getMoney(userId); + long orderCount1 = orderService.count(commodityCode); + long storageCount1 = storageService.count(commodityCode); + + { + SeataRequest request = new SeataRequest(); + request.setCommodityCode(commodityCode); + request.setUserId(userId); + request.setCount(count); + request.setMoney(money); + + HttpEntity httpEntity = new HttpEntity<>(request); + + String url = "http://127.0.0.1:50180/seata"; + assertThrows(Exception.class, () -> { + try { + new RestTemplate().postForObject(url, httpEntity, Map.class); + } catch (Exception e) { + LOGGER.error("Distributed transaction exception: ", e); + String message = e.getMessage(); + assertThat(message).doesNotContain("No instances available"); + assertThat(message).doesNotContain("I/O error on POST request"); + assertThat(message).contains("Insufficient stock"); + throw e; + } + }); + } + + Long money2 = accountService.getMoney(userId); + long orderCount2 = orderService.count(commodityCode); + long storageCount2 = storageService.count(commodityCode); + + // Third: data rollback, database remains unchanged + assertEquals(money1, money2); + assertEquals(orderCount1, orderCount2); + assertEquals(storageCount1, storageCount2); + } +} diff --git a/test-suite/test-native-server/src/test/java/org/apache/seata/server/service/AccountServiceTests.java b/test-suite/test-native-server/src/test/java/org/apache/seata/server/service/AccountServiceTests.java new file mode 100644 index 00000000000..37111c2e67e --- /dev/null +++ b/test-suite/test-native-server/src/test/java/org/apache/seata/server/service/AccountServiceTests.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.seata.server.service; + +import org.apache.seata.server.dto.AccountMoneyRequest; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class AccountServiceTests { + private static final Logger LOGGER = LoggerFactory.getLogger(AccountServiceTests.class); + + @Autowired + private AccountService accountService; + + @Test + void getMoney() { + String userId = "U001"; + Long money = accountService.getMoney(userId); + assertNotNull(money); + } + + @Test + void money_1() { + String userId = "U001"; + + Long money1 = accountService.getMoney(userId); + assertNotNull(money1); + + long money = 1; + AccountMoneyRequest request = new AccountMoneyRequest(); + request.setUserId(userId); + request.setMoney(money); + + accountService.money(request); + + Long money2 = accountService.getMoney(userId); + assertNotNull(money2); + + assertEquals(money1 + money, money2); + } + + @Test + void money_2() { + String userId = "U001"; + + Long money1 = accountService.getMoney(userId); + assertNotNull(money1); + + long money = -1; + AccountMoneyRequest request = new AccountMoneyRequest(); + request.setUserId(userId); + request.setMoney(money); + accountService.money(request); + + Long money2 = accountService.getMoney(userId); + assertNotNull(money2); + + assertEquals(money1 + money, money2); + } + + @Test + void money_3() { + String userId = "U001"; + long money = -10000000; + AccountMoneyRequest request = new AccountMoneyRequest(); + request.setUserId(userId); + request.setMoney(money); + assertThrows(RuntimeException.class, () -> { + accountService.money(request); + }); + } +} diff --git a/test-suite/test-native-server/src/test/java/org/apache/seata/server/service/OrderServiceTests.java b/test-suite/test-native-server/src/test/java/org/apache/seata/server/service/OrderServiceTests.java new file mode 100644 index 00000000000..06444fdc3c9 --- /dev/null +++ b/test-suite/test-native-server/src/test/java/org/apache/seata/server/service/OrderServiceTests.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.seata.server.service; + +import org.apache.seata.server.dto.OrderRequest; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@SpringBootTest +class OrderServiceTests { + private static final Logger LOGGER = LoggerFactory.getLogger(OrderServiceTests.class); + + @Autowired + private OrderService orderService; + + @Test + void order() { + String commodityCode = "A001"; + String userId = "U001"; + long count1 = orderService.count(commodityCode); + + long count = 1; + long money = 1; + OrderRequest request = new OrderRequest(); + request.setUserId(userId); + request.setCommodityCode(commodityCode); + request.setCount(count); + request.setMoney(money); + + orderService.order(request); + + long count2 = orderService.count(commodityCode); + assertEquals(count1 + 1, count2); + } +} diff --git a/test-suite/test-native-server/src/test/java/org/apache/seata/server/service/StorageServiceTests.java b/test-suite/test-native-server/src/test/java/org/apache/seata/server/service/StorageServiceTests.java new file mode 100644 index 00000000000..a880079a6d4 --- /dev/null +++ b/test-suite/test-native-server/src/test/java/org/apache/seata/server/service/StorageServiceTests.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.seata.server.service; + +import org.apache.seata.server.dto.StorageRequest; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class StorageServiceTests { + private static final Logger LOGGER = LoggerFactory.getLogger(StorageServiceTests.class); + + @Autowired + private StorageService storageService; + + @Test + void count() { + String commodityCode = "A001"; + Long count = storageService.count(commodityCode); + assertNotNull(count); + assertNotEquals(0, count); + assertNotEquals(1, count); + } + + @Test + void storage_1() { + String commodityCode = "A001"; + + long count1 = storageService.count(commodityCode); + assertNotEquals(0, count1); + + long count = 1; + StorageRequest request = new StorageRequest(); + request.setCommodityCode(commodityCode); + request.setCount(count); + storageService.storage(request); + + long count2 = storageService.count(commodityCode); + assertNotEquals(0, count2); + assertEquals(count1 + count, count2); + } + + @Test + void storage_2() { + String commodityCode = "A001"; + + long count1 = storageService.count(commodityCode); + assertNotEquals(0, count1); + + long count = -1; + StorageRequest request = new StorageRequest(); + request.setCommodityCode(commodityCode); + request.setCount(count); + storageService.storage(request); + + long count2 = storageService.count(commodityCode); + assertNotEquals(0, count2); + assertEquals(count1 + count, count2); + } + + @Test + void storage_3() { + String commodityCode = "A001"; + Long count = -10000000L; + StorageRequest request = new StorageRequest(); + request.setCommodityCode(commodityCode); + request.setCount(count); + assertThrows(RuntimeException.class, () -> { + storageService.storage(request); + }); + } +}