This is an automated email from the ASF dual-hosted git repository. ningjiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-saga.git
commit d58529f9587f7cb80980ab9b9278b4e029ec07c1 Author: Eric Lee <dagang...@huawei.com> AuthorDate: Mon Dec 25 17:22:34 2017 +0800 SCB-96 added request interceptor --- .../saga/omega/transaction/TxEndedEvent.java | 4 +- .../saga/omega/transaction/TxStartedEvent.java | 4 +- .../omega-transport-resttemplate/pom.xml | 8 ++ .../TransactionHandlerInterceptor.java | 87 ++++++++++++ .../omega/transport/resttemplate/WebConfig.java | 50 +++++++ .../TransactionHandlerInterceptorTest.java | 152 +++++++++++++++++++++ 6 files changed, 301 insertions(+), 4 deletions(-) diff --git a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TxEndedEvent.java b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TxEndedEvent.java index 6cc8f79..c24c1b3 100644 --- a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TxEndedEvent.java +++ b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TxEndedEvent.java @@ -17,8 +17,8 @@ package io.servicecomb.saga.omega.transaction; -class TxEndedEvent extends TxEvent { - TxEndedEvent(String globalTxId, String localTxId, String parentTxId) { +public class TxEndedEvent extends TxEvent { + public TxEndedEvent(String globalTxId, String localTxId, String parentTxId) { super(globalTxId, localTxId, parentTxId); } } diff --git a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TxStartedEvent.java b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TxStartedEvent.java index 830104f..c278f54 100644 --- a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TxStartedEvent.java +++ b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/TxStartedEvent.java @@ -17,9 +17,9 @@ package io.servicecomb.saga.omega.transaction; -class TxStartedEvent extends TxEvent { +public class TxStartedEvent extends TxEvent { - TxStartedEvent(String globalTxId, String localTxId, String parentTxId, Object[] payloads) { + public TxStartedEvent(String globalTxId, String localTxId, String parentTxId, Object[] payloads) { super(globalTxId, localTxId, parentTxId, payloads); } } diff --git a/omega/omega-transport/omega-transport-resttemplate/pom.xml b/omega/omega-transport/omega-transport-resttemplate/pom.xml index d7115d1..5464337 100644 --- a/omega/omega-transport/omega-transport-resttemplate/pom.xml +++ b/omega/omega-transport/omega-transport-resttemplate/pom.xml @@ -38,6 +38,14 @@ <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-webmvc</artifactId> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + </dependency> <dependency> <groupId>org.springframework</groupId> diff --git a/omega/omega-transport/omega-transport-resttemplate/src/main/java/io/servicecomb/saga/omega/transport/resttemplate/TransactionHandlerInterceptor.java b/omega/omega-transport/omega-transport-resttemplate/src/main/java/io/servicecomb/saga/omega/transport/resttemplate/TransactionHandlerInterceptor.java new file mode 100644 index 0000000..56df07d --- /dev/null +++ b/omega/omega-transport/omega-transport-resttemplate/src/main/java/io/servicecomb/saga/omega/transport/resttemplate/TransactionHandlerInterceptor.java @@ -0,0 +1,87 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + */ + +package io.servicecomb.saga.omega.transport.resttemplate; + +import static io.servicecomb.saga.omega.transport.resttemplate.TransactionClientHttpRequestInterceptor.GLOBAL_TX_ID_KEY; +import static io.servicecomb.saga.omega.transport.resttemplate.TransactionClientHttpRequestInterceptor.LOCAL_TX_ID_KEY; + +import java.lang.invoke.MethodHandles; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import io.servicecomb.saga.omega.transaction.MessageSender; +import io.servicecomb.saga.omega.transaction.MessageSerializer; +import io.servicecomb.saga.omega.transaction.TxEndedEvent; +import io.servicecomb.saga.omega.transaction.TxStartedEvent; + +public class TransactionHandlerInterceptor implements HandlerInterceptor { + + private static Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + private final MessageSender sender; + + private final MessageSerializer serializer; + + public TransactionHandlerInterceptor(MessageSender sender, MessageSerializer serializer) { + this.sender = sender; + this.serializer = serializer; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String globalTxId = request.getHeader(GLOBAL_TX_ID_KEY); + if (globalTxId == null) { + LOG.info("no such header: {}", GLOBAL_TX_ID_KEY); + } + String localTxId = request.getHeader(LOCAL_TX_ID_KEY); + if (localTxId == null) { + LOG.info("no such header: {}", LOCAL_TX_ID_KEY); + } + // TODO: 12/25/2017 which content should be inside payloads? + sender.send(serializer.serialize(new TxStartedEvent(globalTxId, localTxId, null, null))); + return true; + } + + @Override + public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, + ModelAndView modelAndView) throws Exception { + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, + Exception e) throws Exception { + String globalTxId = request.getHeader(GLOBAL_TX_ID_KEY); + if (globalTxId == null) { + LOG.info("no such header: {}", GLOBAL_TX_ID_KEY); + } + String localTxId = request.getHeader(LOCAL_TX_ID_KEY); + if (localTxId == null) { + LOG.info("no such header: {}", LOCAL_TX_ID_KEY); + } + sender.send(serializer.serialize(new TxEndedEvent(globalTxId, localTxId, null))); + } +} diff --git a/omega/omega-transport/omega-transport-resttemplate/src/main/java/io/servicecomb/saga/omega/transport/resttemplate/WebConfig.java b/omega/omega-transport/omega-transport-resttemplate/src/main/java/io/servicecomb/saga/omega/transport/resttemplate/WebConfig.java new file mode 100644 index 0000000..7d4fe7f --- /dev/null +++ b/omega/omega-transport/omega-transport-resttemplate/src/main/java/io/servicecomb/saga/omega/transport/resttemplate/WebConfig.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 io.servicecomb.saga.omega.transport.resttemplate; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +import io.servicecomb.saga.omega.transaction.MessageSender; +import io.servicecomb.saga.omega.transaction.MessageSerializer; + +@Configuration +@EnableWebMvc +public class WebConfig extends WebMvcConfigurerAdapter { + + private MessageSender sender; + + private MessageSerializer serializer; + + @Autowired + public WebConfig(MessageSender sender, MessageSerializer serializer) { + this.sender = sender; + this.serializer = serializer; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new TransactionHandlerInterceptor(sender, serializer)); + } +} diff --git a/omega/omega-transport/omega-transport-resttemplate/src/test/java/io/servicecomb/saga/omega/transport/resttemplate/TransactionHandlerInterceptorTest.java b/omega/omega-transport/omega-transport-resttemplate/src/test/java/io/servicecomb/saga/omega/transport/resttemplate/TransactionHandlerInterceptorTest.java new file mode 100644 index 0000000..6d447f5 --- /dev/null +++ b/omega/omega-transport/omega-transport-resttemplate/src/test/java/io/servicecomb/saga/omega/transport/resttemplate/TransactionHandlerInterceptorTest.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package io.servicecomb.saga.omega.transport.resttemplate; + +import static io.servicecomb.saga.omega.transport.resttemplate.TransactionClientHttpRequestInterceptor.GLOBAL_TX_ID_KEY; +import static io.servicecomb.saga.omega.transport.resttemplate.TransactionClientHttpRequestInterceptor.LOCAL_TX_ID_KEY; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.servlet.HandlerInterceptor; + +import io.servicecomb.saga.omega.transaction.MessageSender; +import io.servicecomb.saga.omega.transaction.MessageSerializer; +import io.servicecomb.saga.omega.transport.resttemplate.TransactionHandlerInterceptorTest.MessageConfig; + +@RunWith(SpringRunner.class) +@Import({MessageConfig.class}) +public class TransactionHandlerInterceptorTest { + private static final String TX_STARTED_EVENT = "TxStartedEvent"; + private static final String TX_ENDED_EVENT = "TxEndedEvent"; + private static final String globalTxId = UUID.randomUUID().toString(); + private static final String localTxId = UUID.randomUUID().toString(); + + @Autowired + private MessageSender sender; + + @Autowired + private MessageSerializer serializer; + + @Autowired + private TransactionHandlerInterceptor requestInterceptor; + + @Autowired + private List<byte[]> messages; + + private HttpServletRequest request = mock(HttpServletRequest.class); + + private HttpServletResponse response = mock(HttpServletResponse.class); + + @After + public void tearDown() throws Exception { + messages.clear(); + } + + @Test + public void preInterceptHeaderValueAndSendOut() throws Exception { + when(request.getHeader(GLOBAL_TX_ID_KEY)).thenReturn(globalTxId); + when(request.getHeader(LOCAL_TX_ID_KEY)).thenReturn(localTxId); + + requestInterceptor.preHandle(request, response, null); + + assertThat(messages.size(), is(1)); + String deserializedString = new String(messages.get(0)); + assertThat(deserializedString.contains(TX_STARTED_EVENT), is(true)); + assertThat(deserializedString.startsWith(globalTxId), is(true)); + assertThat(deserializedString.contains(localTxId), is(true)); + } + + @Test + public void postInterceptHeaderValueAndSendOut() throws Exception { + when(request.getHeader(GLOBAL_TX_ID_KEY)).thenReturn(globalTxId); + when(request.getHeader(LOCAL_TX_ID_KEY)).thenReturn(localTxId); + + requestInterceptor.afterCompletion(request, response, null, null); + + assertThat(messages.size(), is(1)); + String deserializedString = new String(messages.get(0)); + assertThat(deserializedString.contains(TX_ENDED_EVENT), is(true)); + assertThat(deserializedString.startsWith(globalTxId), is(true)); + assertThat(deserializedString.contains(localTxId), is(true)); + } + + @Configuration + static class MessageConfig { + private final List<byte[]> messages = new ArrayList<>(); + + @Bean + List<byte[]> messages() { + return messages; + } + + @Bean + MessageSender sender() { + return messages::add; + } + + @Bean + MessageSerializer serializer() { + return event -> { + if (TX_STARTED_EVENT.equals(event.type())) { + return txStartedEvent(event.globalTxId(), + event.localTxId(), + event.parentTxId(), + event.payloads()).getBytes(); + } + return txEndedEvent(event.globalTxId(), + event.localTxId(), + event.parentTxId()).getBytes(); + }; + } + + @Bean + HandlerInterceptor handlerInterceptor(MessageSender sender, MessageSerializer serializer) { + return new TransactionHandlerInterceptor(sender, serializer); + } + } + + private static String txStartedEvent(String globalTxId, + String localTxId, + String parentTxId, + Object[] payloads) { + return globalTxId + ":" + localTxId + ":" + parentTxId + ":" + TX_STARTED_EVENT + ":" + Arrays.toString(payloads); + } + + private static String txEndedEvent(String globalTxId, String localTxId, String parentTxId) { + return globalTxId + ":" + localTxId + ":" + parentTxId + ":" + TX_ENDED_EVENT; + } +} \ No newline at end of file -- To stop receiving notification emails like this one, please contact "commits@servicecomb.apache.org" <commits@servicecomb.apache.org>.