This is an automated email from the ASF dual-hosted git repository. ningjiang pushed a commit to branch 0.2.x in repository https://gitbox.apache.org/repos/asf/servicecomb-saga.git
commit f9b8be5a3c3262954e23c8136265ad68a64b67d6 Author: Lionel_pang <pangming...@163.com> AuthorDate: Wed Jul 11 11:08:59 2018 +0800 SCB-730 Add Feign transport for supporting Spring Cloud (#212) * 增加spring cloud下服务见使用openfeign进行服务间通讯使用saga实现分布式事务。实现feign接口调用过程中传递全局事务ID和本地事务ID。 * 增加feign模块。 * add the ASF header license to the source file * the ASF header license to the spring.factories and modiy the spring-test scop. * the ASF header license to the source file --- .../omega-transport/omega-transport-feign/pom.xml | 77 ++++++++++++++++++++++ .../transport/feign/FeignAutoConfiguration.java | 36 ++++++++++ .../feign/FeignClientRequestInterceptor.java | 57 ++++++++++++++++ .../src/main/resources/META-INF/spring.factories | 18 +++++ .../feign/FeignAutoConfigurationTest.java | 72 ++++++++++++++++++++ omega/omega-transport/pom.xml | 1 + 6 files changed, 261 insertions(+) diff --git a/omega/omega-transport/omega-transport-feign/pom.xml b/omega/omega-transport/omega-transport-feign/pom.xml new file mode 100644 index 0000000..fd9b050 --- /dev/null +++ b/omega/omega-transport/omega-transport-feign/pom.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>omega-transport</artifactId> + <groupId>org.apache.servicecomb.saga</groupId> + <version>0.3.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>omega-transport-feign</artifactId> + <dependencies> + <dependency> + <groupId>io.github.openfeign</groupId> + <artifactId>feign-core</artifactId> + <version>9.5.1</version> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-web</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-webmvc</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-autoconfigure</artifactId> + </dependency> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + +</project> diff --git a/omega/omega-transport/omega-transport-feign/src/main/java/org/apache/servicecomb/saga/omega/transport/feign/FeignAutoConfiguration.java b/omega/omega-transport/omega-transport-feign/src/main/java/org/apache/servicecomb/saga/omega/transport/feign/FeignAutoConfiguration.java new file mode 100644 index 0000000..0edc663 --- /dev/null +++ b/omega/omega-transport/omega-transport-feign/src/main/java/org/apache/servicecomb/saga/omega/transport/feign/FeignAutoConfiguration.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.saga.omega.transport.feign; + +import feign.RequestInterceptor; +import org.apache.servicecomb.saga.omega.context.OmegaContext; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FeignAutoConfiguration { + + @Bean + @ConditionalOnClass(RequestInterceptor.class) + @ConditionalOnBean(OmegaContext.class) + public RequestInterceptor feignClientRequestInterceptor(OmegaContext omegaContext){ + return new FeignClientRequestInterceptor(omegaContext); + } +} diff --git a/omega/omega-transport/omega-transport-feign/src/main/java/org/apache/servicecomb/saga/omega/transport/feign/FeignClientRequestInterceptor.java b/omega/omega-transport/omega-transport-feign/src/main/java/org/apache/servicecomb/saga/omega/transport/feign/FeignClientRequestInterceptor.java new file mode 100644 index 0000000..c679ed0 --- /dev/null +++ b/omega/omega-transport/omega-transport-feign/src/main/java/org/apache/servicecomb/saga/omega/transport/feign/FeignClientRequestInterceptor.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.saga.omega.transport.feign; + +import feign.RequestInterceptor; +import feign.RequestTemplate; +import org.apache.servicecomb.saga.omega.context.OmegaContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.invoke.MethodHandles; + +import static org.apache.servicecomb.saga.omega.context.OmegaContext.GLOBAL_TX_ID_KEY; +import static org.apache.servicecomb.saga.omega.context.OmegaContext.LOCAL_TX_ID_KEY; + +/** + * 增加Feign拦截器,实现spring cloud下feign调用传递全局事务和本地事务。 + * create by lionel on 2018/07/05 + */ +public class FeignClientRequestInterceptor implements RequestInterceptor { + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + private final OmegaContext omegaContext; + + public FeignClientRequestInterceptor(OmegaContext omegaContext) { + this.omegaContext = omegaContext; + } + + @Override + public void apply(RequestTemplate input) { + if (omegaContext!= null && omegaContext.globalTxId() != null) { + input.header(GLOBAL_TX_ID_KEY, omegaContext.globalTxId()); + input.header(LOCAL_TX_ID_KEY, omegaContext.localTxId()); + + LOG.debug("Added {} {} and {} {} to request header", + GLOBAL_TX_ID_KEY, + omegaContext.globalTxId(), + LOCAL_TX_ID_KEY, + omegaContext.localTxId()); + } + } +} diff --git a/omega/omega-transport/omega-transport-feign/src/main/resources/META-INF/spring.factories b/omega/omega-transport/omega-transport-feign/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..75c16ba --- /dev/null +++ b/omega/omega-transport/omega-transport-feign/src/main/resources/META-INF/spring.factories @@ -0,0 +1,18 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## --------------------------------------------------------------------------- +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + org.apache.servicecomb.saga.omega.transport.feign.FeignAutoConfiguration \ No newline at end of file diff --git a/omega/omega-transport/omega-transport-feign/src/test/java/org/apache/servicecomb/saga/omega/transport/feign/FeignAutoConfigurationTest.java b/omega/omega-transport/omega-transport-feign/src/test/java/org/apache/servicecomb/saga/omega/transport/feign/FeignAutoConfigurationTest.java new file mode 100644 index 0000000..f10f89a --- /dev/null +++ b/omega/omega-transport/omega-transport-feign/src/test/java/org/apache/servicecomb/saga/omega/transport/feign/FeignAutoConfigurationTest.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.servicecomb.saga.omega.transport.feign; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; + +import java.util.ArrayList; +import java.util.UUID; + +import feign.RequestInterceptor; +import feign.RequestTemplate; +import org.apache.servicecomb.saga.omega.context.OmegaContext; +import org.junit.Before; +import org.junit.Test; + +public class FeignAutoConfigurationTest{ + + private static final String globalTxId = UUID.randomUUID().toString(); + + private static final String localTxId = UUID.randomUUID().toString(); + + private final OmegaContext omegaContext = new OmegaContext(() -> "ignored"); + + private RequestTemplate requestTemplate = new RequestTemplate(); // mock(RequestTemplate.class); + + private final RequestInterceptor feignClientRequestInterceptor = new FeignClientRequestInterceptor(omegaContext); + + @Before + public void setUp() { + omegaContext.clear(); + } + + @Test + public void setUpOmegaContextInTransactionRequest() throws Exception { + omegaContext.setGlobalTxId(globalTxId); + omegaContext.setLocalTxId(localTxId); + + feignClientRequestInterceptor.apply(requestTemplate); // .preHandle(request, response, null); + + assertThat((new ArrayList(requestTemplate.headers().get(OmegaContext.GLOBAL_TX_ID_KEY))).get(0), is(globalTxId)); + assertThat((new ArrayList(requestTemplate.headers().get(OmegaContext.LOCAL_TX_ID_KEY))).get(0), is(localTxId)); + } + + @Test + public void doNothingInNonTransactionRequest() throws Exception { + omegaContext.setGlobalTxId(null); + omegaContext.setLocalTxId(null); + + feignClientRequestInterceptor.apply(requestTemplate); + + assertThat(requestTemplate.headers().get(OmegaContext.GLOBAL_TX_ID_KEY), is(nullValue())); + assertThat(requestTemplate.headers().get(OmegaContext.LOCAL_TX_ID_KEY), is(nullValue())); + } +} \ No newline at end of file diff --git a/omega/omega-transport/pom.xml b/omega/omega-transport/pom.xml index 697f2d7..23599b2 100644 --- a/omega/omega-transport/pom.xml +++ b/omega/omega-transport/pom.xml @@ -35,6 +35,7 @@ <module>omega-transport-resttemplate</module> <module>omega-transport-servicecomb</module> <module>omega-transport-dubbo</module> + <module>omega-transport-feign</module> </modules> <dependencies>