You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2017/12/27 04:55:08 UTC

[incubator-servicecomb-saga] 01/11: SCB-96 added request interceptor

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 <da...@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" <co...@servicecomb.apache.org>.