You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by se...@apache.org on 2017/12/26 10:41:24 UTC

[incubator-servicecomb-saga] 06/07: SCB-97 glued omega & alpha together

This is an automated email from the ASF dual-hosted git repository.

seanyinx pushed a commit to branch SCB-97_alpha_omega_bonding
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-saga.git

commit 84b7f040bc7576f089253440a5aab174728219ca
Author: seanyinx <se...@huawei.com>
AuthorDate: Tue Dec 26 17:06:23 2017 +0800

    SCB-97 glued omega & alpha together
    
    Signed-off-by: seanyinx <se...@huawei.com>
---
 .../io/servicecomb/saga/alpha/core/TxEvent.java    |  12 +-
 alpha/alpha-server/pom.xml                         |  32 +++++
 .../alpha/server/SwiftTxEventEndpointImpl.java     |   4 +-
 .../saga/alpha/server/TxEventEnvelope.java         |   4 +-
 .../src/main/resources/application.yaml            |  31 +++++
 .../alpha-server/src/main/resources/log4j2.xml     |  40 ++----
 .../src/main/resources/schema-mysql.sql            |  11 ++
 integration-tests/coverage-aggregate/pom.xml       |   8 ++
 .../pack-tests}/pom.xml                            | 140 ++++++---------------
 .../pack/tests/GreetingApplication.java            |  15 ++-
 .../integration/pack/tests/GreetingController.java |  52 ++++++++
 .../integration/pack/tests/GreetingService.java    |  18 ++-
 .../saga/integration/pack/tests/PackIT.java        |  52 ++++++++
 integration-tests/pom.xml                          |   1 +
 .../connector/thrift/ThriftMessageSender.java      |  21 +++-
 {integration-tests => omega/omega-format}/pom.xml  |  43 ++++---
 .../saga/omega/format/NativeMessageFormat.java     |  53 ++++++++
 .../saga/omega/format/NativeMessageFormatTest.java |  70 +++++++++++
 omega/{ => omega-spring-starter}/pom.xml           |  53 ++++----
 .../saga/omega/spring/EnableOmega.java}            |  17 ++-
 .../saga/omega/spring/OmegaSpringConfig.java       |  52 ++++++++
 .../spring/CompensableMethodCheckingCallback.java  |   3 +-
 .../spring/TransactionAspectConfig.java            |   2 +-
 .../spring/CompensableAnnotationCheckingTest.java  |   2 +-
 .../omega/transaction/MessageDeserializer.java     |   2 +-
 ...essageDeserializer.java => OmegaException.java} |   7 +-
 omega/pom.xml                                      |   2 +
 pom.xml                                            |  27 +++-
 .../conditional-transaction-demo-tests/pom.xml     |   2 +-
 .../demo-tests/pom.xml                             |   2 +-
 30 files changed, 571 insertions(+), 207 deletions(-)

diff --git a/alpha/alpha-core/src/main/java/io/servicecomb/saga/alpha/core/TxEvent.java b/alpha/alpha-core/src/main/java/io/servicecomb/saga/alpha/core/TxEvent.java
index abd8fbd..2d0a19b 100644
--- a/alpha/alpha-core/src/main/java/io/servicecomb/saga/alpha/core/TxEvent.java
+++ b/alpha/alpha-core/src/main/java/io/servicecomb/saga/alpha/core/TxEvent.java
@@ -17,8 +17,10 @@
 
 package io.servicecomb.saga.alpha.core;
 
+import java.util.Date;
+
 public class TxEvent {
-  private long timestamp;
+  private Date creationTime;
   private String globalTxId;
   private String localTxId;
   private String parentTxId;
@@ -28,8 +30,8 @@ public class TxEvent {
   private TxEvent() {
   }
 
-  public TxEvent(long timestamp, String globalTxId, String localTxId, String parentTxId, String type, byte[] payloads) {
-    this.timestamp = timestamp;
+  public TxEvent(Date creationTime, String globalTxId, String localTxId, String parentTxId, String type, byte[] payloads) {
+    this.creationTime = creationTime;
     this.globalTxId = globalTxId;
     this.localTxId = localTxId;
     this.parentTxId = parentTxId;
@@ -37,8 +39,8 @@ public class TxEvent {
     this.payloads = payloads;
   }
 
-  public long timestamp() {
-    return timestamp;
+  public Date creationTime() {
+    return creationTime;
   }
 
   public String globalTxId() {
diff --git a/alpha/alpha-server/pom.xml b/alpha/alpha-server/pom.xml
index 78723d5..4bc347e 100644
--- a/alpha/alpha-server/pom.xml
+++ b/alpha/alpha-server/pom.xml
@@ -65,6 +65,10 @@
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-jpa</artifactId>
     </dependency>
+    <dependency>
+      <groupId>mysql</groupId>
+      <artifactId>mysql-connector-java</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>org.springframework.boot</groupId>
@@ -87,6 +91,34 @@
         <artifactId>swift-maven-plugin</artifactId>
       </plugin>
 -->
+      <!-- mixin plugin configurations declared in another pom,
+      just like importing dependencies managed in another pom -->
+      <plugin>
+        <groupId>com.github.odavid.maven.plugins</groupId>
+        <artifactId>mixin-maven-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-maven-plugin</artifactId>
+      </plugin>
     </plugins>
   </build>
+
+  <profiles>
+    <profile>
+      <id>docker</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>io.fabric8</groupId>
+            <artifactId>docker-maven-plugin</artifactId>
+          </plugin>
+          <plugin>
+            <groupId>org.commonjava.maven.plugins</groupId>
+            <artifactId>directory-maven-plugin</artifactId>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
 </project>
\ No newline at end of file
diff --git a/alpha/alpha-server/src/main/java/io/servicecomb/saga/alpha/server/SwiftTxEventEndpointImpl.java b/alpha/alpha-server/src/main/java/io/servicecomb/saga/alpha/server/SwiftTxEventEndpointImpl.java
index 4fd7d87..3ae39f6 100644
--- a/alpha/alpha-server/src/main/java/io/servicecomb/saga/alpha/server/SwiftTxEventEndpointImpl.java
+++ b/alpha/alpha-server/src/main/java/io/servicecomb/saga/alpha/server/SwiftTxEventEndpointImpl.java
@@ -17,6 +17,8 @@
 
 package io.servicecomb.saga.alpha.server;
 
+import java.util.Date;
+
 import io.servicecomb.saga.alpha.core.TxEvent;
 import io.servicecomb.saga.alpha.core.TxEventRepository;
 import io.servicecomb.saga.pack.contracts.thrift.SwiftTxEvent;
@@ -33,7 +35,7 @@ class SwiftTxEventEndpointImpl implements SwiftTxEventEndpoint {
   @Override
   public void handle(SwiftTxEvent message) {
     eventRepository.save(new TxEvent(
-        message.timestamp(),
+        new Date(message.timestamp()),
         message.globalTxId(),
         message.localTxId(),
         message.parentTxId(),
diff --git a/alpha/alpha-server/src/main/java/io/servicecomb/saga/alpha/server/TxEventEnvelope.java b/alpha/alpha-server/src/main/java/io/servicecomb/saga/alpha/server/TxEventEnvelope.java
index d5428c4..adbb28e 100644
--- a/alpha/alpha-server/src/main/java/io/servicecomb/saga/alpha/server/TxEventEnvelope.java
+++ b/alpha/alpha-server/src/main/java/io/servicecomb/saga/alpha/server/TxEventEnvelope.java
@@ -40,8 +40,8 @@ class TxEventEnvelope {
     this.event = event;
   }
 
-  public long timestamp() {
-    return event.timestamp();
+  public long creationTime() {
+    return event.creationTime().getTime();
   }
 
   String globalTxId() {
diff --git a/alpha/alpha-server/src/main/resources/application.yaml b/alpha/alpha-server/src/main/resources/application.yaml
new file mode 100644
index 0000000..9b166c8
--- /dev/null
+++ b/alpha/alpha-server/src/main/resources/application.yaml
@@ -0,0 +1,31 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements.  See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License.  You may obtain a copy of the License at
+##
+##      http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+spring:
+  profiles: prd
+  datasource:
+    username: saga
+    password: password
+    driver-class-name: com.mysql.jdbc.Driver
+    url: jdbc:mysql://mysql.servicecomb.io:3306/saga?useSSL=false
+    platform: mysql
+    continue-on-error: true
+  jpa:
+    properties:
+      hibernate:
+        dialect: org.hibernate.dialect.MySQL5Dialect
+    hibernate:
+      ddl-auto: none
diff --git a/integration-tests/pom.xml b/alpha/alpha-server/src/main/resources/log4j2.xml
similarity index 50%
copy from integration-tests/pom.xml
copy to alpha/alpha-server/src/main/resources/log4j2.xml
index 8b71db2..cae04cb 100644
--- a/integration-tests/pom.xml
+++ b/alpha/alpha-server/src/main/resources/log4j2.xml
@@ -16,31 +16,15 @@
   ~ 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>saga</artifactId>
-    <groupId>io.servicecomb.saga</groupId>
-    <version>0.0.3-SNAPSHOT</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-
-  <groupId>io.servicecomb.saga.tests</groupId>
-  <artifactId>integration-tests</artifactId>
-  <packaging>pom</packaging>
-  <modules>
-    <module>coverage-aggregate</module>
-  </modules>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-deploy-plugin</artifactId>
-        <configuration>
-          <skip>true</skip>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-
-</project>
+<Configuration status="WARN">
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
+    </Console>
+  </Appenders>
+  <Loggers>
+    <AsyncRoot level="info">
+      <AppenderRef ref="Console"/>
+    </AsyncRoot>
+  </Loggers>
+</Configuration>
diff --git a/alpha/alpha-server/src/main/resources/schema-mysql.sql b/alpha/alpha-server/src/main/resources/schema-mysql.sql
new file mode 100644
index 0000000..c3175ed
--- /dev/null
+++ b/alpha/alpha-server/src/main/resources/schema-mysql.sql
@@ -0,0 +1,11 @@
+CREATE TABLE IF NOT EXISTS `tx_event_envelope` (
+  `surrogate_id` bigint NOT NULL AUTO_INCREMENT,
+  `creation_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+  `global_tx_id` varchar(36) NOT NULL,
+  `local_tx_id` varchar(36) NOT NULL,
+  `parent_tx_id` varchar(36) DEFAULT NULL,
+  `type` varchar(50) NOT NULL,
+  `payloads` varbinary(10240),
+  PRIMARY KEY (`surrogate_id`),
+  INDEX `running_sagas_index` (`global_tx_id`, `local_tx_id`, `type`)
+) DEFAULT CHARSET=utf8;
diff --git a/integration-tests/coverage-aggregate/pom.xml b/integration-tests/coverage-aggregate/pom.xml
index a32f598..452fc56 100644
--- a/integration-tests/coverage-aggregate/pom.xml
+++ b/integration-tests/coverage-aggregate/pom.xml
@@ -63,6 +63,14 @@
       <groupId>io.servicecomb.saga</groupId>
       <artifactId>omega-transport-resttemplate</artifactId>
     </dependency>
+    <dependency>
+      <groupId>io.servicecomb.saga</groupId>
+      <artifactId>omega-format</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.servicecomb.saga</groupId>
+      <artifactId>alpha-server</artifactId>
+    </dependency>
   </dependencies>
 
   <profiles>
diff --git a/saga-demo/conditional-transaction-demo/conditional-transaction-demo-tests/pom.xml b/integration-tests/pack-tests/pom.xml
similarity index 64%
copy from saga-demo/conditional-transaction-demo/conditional-transaction-demo-tests/pom.xml
copy to integration-tests/pack-tests/pom.xml
index f1a5bba..bc7717c 100644
--- a/saga-demo/conditional-transaction-demo/conditional-transaction-demo-tests/pom.xml
+++ b/integration-tests/pack-tests/pom.xml
@@ -16,18 +16,36 @@
   ~ 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">
+<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>conditional-transaction-demo</artifactId>
-    <groupId>io.servicecomb.saga.demo</groupId>
+    <artifactId>integration-tests</artifactId>
+    <groupId>io.servicecomb.saga.tests</groupId>
     <version>0.0.3-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
-  <artifactId>conditional-transaction-demo-tests</artifactId>
+  <artifactId>pack-tests</artifactId>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-dependencies</artifactId>
+        <version>${spring.boot.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
 
   <dependencies>
     <dependency>
+      <groupId>io.servicecomb.saga</groupId>
+      <artifactId>omega-spring-starter</artifactId>
+    </dependency>
+    <dependency>
       <groupId>commons-logging</groupId>
       <artifactId>commons-logging</artifactId>
       <version>1.2</version>
@@ -44,6 +62,16 @@
     </dependency>
     <dependency>
       <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-test</artifactId>
       <scope>test</scope>
     </dependency>
@@ -86,107 +114,19 @@
               </run>
             </image>
             <image>
-              <name>payment:${project.version}</name>
-              <alias>payment</alias>
-              <run>
-                <env>
-                  <JAVA_OPTS />
-                </env>
-                <wait>
-                  <log>Tomcat started on port</log>
-                  <tcp>
-                    <ports>
-                      <port>8080</port>
-                    </ports>
-                  </tcp>
-                  <time>120000</time>
-                </wait>
-                <ports>
-                  <port>payment.port:8080</port>
-                </ports>
-              </run>
-            </image>
-            <image>
-              <name>membership:${project.version}</name>
-              <alias>membership</alias>
-              <run>
-                <env>
-                  <JAVA_OPTS />
-                </env>
-                <wait>
-                  <log>Tomcat started on port</log>
-                  <tcp>
-                    <ports>
-                      <port>8080</port>
-                    </ports>
-                  </tcp>
-                  <time>120000</time>
-                </wait>
-                <ports>
-                  <port>membership.port:8080</port>
-                </ports>
-              </run>
-            </image>
-            <image>
-              <name>inventory:${project.version}</name>
-              <alias>inventory</alias>
-              <run>
-                <env>
-                  <JAVA_OPTS />
-                </env>
-                <wait>
-                  <log>Tomcat started on port</log>
-                  <tcp>
-                    <ports>
-                      <port>8080</port>
-                    </ports>
-                  </tcp>
-                  <time>120000</time>
-                </wait>
-                <ports>
-                  <port>inventory.port:8080</port>
-                </ports>
-              </run>
-            </image>
-            <image>
-              <name>supplier:${project.version}</name>
-              <alias>supplier</alias>
-              <run>
-                <env>
-                  <JAVA_OPTS />
-                </env>
-                <wait>
-                  <log>Tomcat started on port</log>
-                  <tcp>
-                    <ports>
-                      <port>8080</port>
-                    </ports>
-                  </tcp>
-                  <time>120000</time>
-                </wait>
-                <ports>
-                  <port>supplier.port:8080</port>
-                </ports>
-              </run>
-            </image>
-            <image>
-              <name>saga-spring:${project.version}</name>
-              <alias>saga</alias>
+              <name>alpha-server:${project.version}</name>
+              <alias>alpha</alias>
               <run>
                 <env>
                   <JAVA_OPTS>
-                    -Dspring.profiles.active=prd -Dspring.main.webEnvironment=true
+                    -Dspring.profiles.active=prd
                   </JAVA_OPTS>
                 </env>
                 <links>
                   <link>mysql:mysql.servicecomb.io</link>
-                  <link>payment:payment.servicecomb.io</link>
-                  <link>membership:membership.servicecomb.io</link>
-                  <link>inventory:inventory.servicecomb.io</link>
-                  <link>supplier:supplier.servicecomb.io</link>
                 </links>
                 <wait>
-                  <log>Tomcat started on port</log>
+                  <log>Started [a-zA-Z]+ in [0-9.]+ seconds</log>
                   <tcp>
                     <ports>
                       <port>8080</port>
@@ -195,7 +135,7 @@
                   <time>120000</time>
                 </wait>
                 <ports>
-                  <port>saga.port:8080</port>
+                  <port>alpha.port:8080</port>
                 </ports>
                 <dependsOn>
                   <dependsOn>mysql</dependsOn>
@@ -250,11 +190,11 @@
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-failsafe-plugin</artifactId>
-            <version>2.19.1</version>
+            <version>${maven.failsafe.version}</version>
             <configuration>
               <systemPropertyVariables>
                 <saga.address>
-                  http://${docker.hostname}:${saga.port}
+                  http://${docker.hostname}:${alpha.port}
                 </saga.address>
               </systemPropertyVariables>
               <argLine>${jacoco.failsafe.argLine}</argLine>
@@ -302,4 +242,4 @@
     </profile>
   </profiles>
 
-</project>
+</project>
\ No newline at end of file
diff --git a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java b/integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/GreetingApplication.java
similarity index 66%
copy from omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java
copy to integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/GreetingApplication.java
index d4315b3..24bce7a 100644
--- a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java
+++ b/integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/GreetingApplication.java
@@ -15,8 +15,17 @@
  * limitations under the License.
  */
 
-package io.servicecomb.saga.omega.transaction;
+package io.servicecomb.saga.integration.pack.tests;
 
-public interface MessageDeserializer {
-  <T> T deserialize(byte[] message);
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import io.servicecomb.saga.omega.spring.EnableOmega;
+
+@EnableOmega
+@SpringBootApplication
+public class GreetingApplication {
+  public static void main(String[] args) {
+    SpringApplication.run(GreetingApplication.class, args);
+  }
 }
diff --git a/integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/GreetingController.java b/integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/GreetingController.java
new file mode 100644
index 0000000..11aa0e8
--- /dev/null
+++ b/integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/GreetingController.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.servicecomb.saga.integration.pack.tests;
+
+import java.util.UUID;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import io.servicecomb.saga.omega.context.OmegaContext;
+
+@Controller
+@RequestMapping("/")
+public class GreetingController {
+  private final GreetingService greetingService;
+  private final OmegaContext context;
+
+  @Autowired
+  public GreetingController(GreetingService greetingService, OmegaContext context) {
+    this.greetingService = greetingService;
+    this.context = context;
+  }
+
+
+  @GetMapping("/greet")
+  ResponseEntity<String> greet(@RequestParam String name) {
+    // TODO: 2017/12/26 to be removed when tx id retrieval is done
+    context.setGlobalTxId(UUID.randomUUID().toString());
+    context.setLocalTxId(UUID.randomUUID().toString());
+
+    return ResponseEntity.ok(greetingService.greet(name));
+  }
+}
diff --git a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java b/integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/GreetingService.java
similarity index 67%
copy from omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java
copy to integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/GreetingService.java
index d4315b3..d65899b 100644
--- a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java
+++ b/integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/GreetingService.java
@@ -15,8 +15,20 @@
  * limitations under the License.
  */
 
-package io.servicecomb.saga.omega.transaction;
+package io.servicecomb.saga.integration.pack.tests;
 
-public interface MessageDeserializer {
-  <T> T deserialize(byte[] message);
+import org.springframework.stereotype.Service;
+
+import io.servicecomb.saga.omega.transaction.annotations.Compensable;
+
+@Service
+public class GreetingService {
+  @Compensable(compensationMethod = "goodbye")
+  String greet(String name) {
+    return "Greetings, " + name;
+  }
+
+  String goodbye(String name) {
+    return "Goodbye, " + name;
+  }
 }
diff --git a/integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/PackIT.java b/integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/PackIT.java
new file mode 100644
index 0000000..ad6bed1
--- /dev/null
+++ b/integration-tests/pack-tests/src/test/java/io/servicecomb/saga/integration/pack/tests/PackIT.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.servicecomb.saga.integration.pack.tests;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.springframework.http.HttpStatus.OK;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import io.servicecomb.saga.omega.context.OmegaContext;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = GreetingApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"alpha.cluster.address=localhost:32782"})
+public class PackIT {
+  @Autowired
+  private TestRestTemplate restTemplate;
+
+  @Autowired
+  private OmegaContext omegaContext;
+
+
+  @Test
+  public void updatesTxStateToAlpha() throws Exception {
+    ResponseEntity<String> entity = restTemplate.getForEntity("/greet?name={name}", String.class, "mike");
+
+    assertThat(entity.getStatusCode(), is(OK));
+    assertThat(entity.getBody(), is("Greetings, mike"));
+  }
+}
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 8b71db2..cf1cc99 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -29,6 +29,7 @@
   <packaging>pom</packaging>
   <modules>
     <module>coverage-aggregate</module>
+    <module>pack-tests</module>
   </modules>
 
   <build>
diff --git a/omega/omega-connector/omega-connector-thrift/src/main/java/io/servicecomb/saga/omega/connector/thrift/ThriftMessageSender.java b/omega/omega-connector/omega-connector-thrift/src/main/java/io/servicecomb/saga/omega/connector/thrift/ThriftMessageSender.java
index ed44e0c..bbf9bfa 100644
--- a/omega/omega-connector/omega-connector-thrift/src/main/java/io/servicecomb/saga/omega/connector/thrift/ThriftMessageSender.java
+++ b/omega/omega-connector/omega-connector-thrift/src/main/java/io/servicecomb/saga/omega/connector/thrift/ThriftMessageSender.java
@@ -17,17 +17,34 @@
 
 package io.servicecomb.saga.omega.connector.thrift;
 
+import static com.google.common.net.HostAndPort.fromParts;
+
+import java.util.concurrent.ExecutionException;
+
+import com.facebook.nifty.client.FramedClientConnector;
+import com.facebook.swift.service.ThriftClientManager;
+
 import io.servicecomb.saga.omega.transaction.MessageSender;
 import io.servicecomb.saga.omega.transaction.MessageSerializer;
 import io.servicecomb.saga.omega.transaction.TxEvent;
 import io.servicecomb.saga.pack.contracts.thrift.SwiftTxEvent;
 import io.servicecomb.saga.pack.contracts.thrift.SwiftTxEventEndpoint;
 
-class ThriftMessageSender implements MessageSender {
-
+public class ThriftMessageSender implements MessageSender {
+  private static final ThriftClientManager clientManager = new ThriftClientManager();
   private final SwiftTxEventEndpoint eventService;
   private final MessageSerializer serializer;
 
+  public static ThriftMessageSender create(String host, int port, MessageSerializer serializer) {
+    FramedClientConnector connector = new FramedClientConnector(fromParts(host, port));
+    try {
+      SwiftTxEventEndpoint endpoint = clientManager.createClient(connector, SwiftTxEventEndpoint.class).get();
+      return new ThriftMessageSender(endpoint, serializer);
+    } catch (InterruptedException | ExecutionException e) {
+      throw new IllegalStateException("Failed to create transaction event endpoint client to " + host + ":" + port, e);
+    }
+  }
+
   ThriftMessageSender(SwiftTxEventEndpoint eventService, MessageSerializer serializer) {
     this.eventService = eventService;
     this.serializer = serializer;
diff --git a/integration-tests/pom.xml b/omega/omega-format/pom.xml
similarity index 56%
copy from integration-tests/pom.xml
copy to omega/omega-format/pom.xml
index 8b71db2..e7d2dc9 100644
--- a/integration-tests/pom.xml
+++ b/omega/omega-format/pom.xml
@@ -16,31 +16,36 @@
   ~ 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">
+<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>saga</artifactId>
+    <artifactId>omega</artifactId>
     <groupId>io.servicecomb.saga</groupId>
     <version>0.0.3-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
-  <groupId>io.servicecomb.saga.tests</groupId>
-  <artifactId>integration-tests</artifactId>
-  <packaging>pom</packaging>
-  <modules>
-    <module>coverage-aggregate</module>
-  </modules>
+  <artifactId>omega-format</artifactId>
 
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-deploy-plugin</artifactId>
-        <configuration>
-          <skip>true</skip>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
+  <dependencies>
+    <dependency>
+      <groupId>io.servicecomb.saga</groupId>
+      <artifactId>omega-transaction</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-all</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.github.seanyinx</groupId>
+      <artifactId>unit-scaffolding</artifactId>
+    </dependency>
+  </dependencies>
 
 </project>
diff --git a/omega/omega-format/src/main/java/io/servicecomb/saga/omega/format/NativeMessageFormat.java b/omega/omega-format/src/main/java/io/servicecomb/saga/omega/format/NativeMessageFormat.java
new file mode 100644
index 0000000..14b1d29
--- /dev/null
+++ b/omega/omega-format/src/main/java/io/servicecomb/saga/omega/format/NativeMessageFormat.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.servicecomb.saga.omega.format;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import io.servicecomb.saga.omega.transaction.MessageDeserializer;
+import io.servicecomb.saga.omega.transaction.MessageSerializer;
+import io.servicecomb.saga.omega.transaction.OmegaException;
+import io.servicecomb.saga.omega.transaction.TxEvent;
+
+public class NativeMessageFormat implements MessageSerializer, MessageDeserializer {
+  @Override
+  public byte[] serialize(TxEvent event) {
+    try {
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      try (ObjectOutputStream outputStream = new ObjectOutputStream(out)) {
+        outputStream.writeObject(event.payloads());
+        return out.toByteArray();
+      }
+    } catch (IOException e) {
+      throw new OmegaException("Unable to serialize event with global tx id " + event.globalTxId(), e);
+    }
+  }
+
+  @Override
+  public Object[] deserialize(byte[] message) {
+    try (ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(message))) {
+      return (Object[]) inputStream.readObject();
+    } catch (IOException | ClassNotFoundException e) {
+      throw new OmegaException("Unable to deserialize message", e);
+    }
+  }
+}
diff --git a/omega/omega-format/src/test/java/io/servicecomb/saga/omega/format/NativeMessageFormatTest.java b/omega/omega-format/src/test/java/io/servicecomb/saga/omega/format/NativeMessageFormatTest.java
new file mode 100644
index 0000000..4c93270
--- /dev/null
+++ b/omega/omega-format/src/test/java/io/servicecomb/saga/omega/format/NativeMessageFormatTest.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.servicecomb.saga.omega.format;
+
+import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing;
+import static java.util.Arrays.asList;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.startsWith;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+
+import io.servicecomb.saga.omega.transaction.OmegaException;
+import io.servicecomb.saga.omega.transaction.TxEvent;
+
+public class NativeMessageFormatTest {
+
+  private final NativeMessageFormat format = new NativeMessageFormat();
+
+  @Test
+  public void serializeObjectIntoBytes() throws Exception {
+    byte[] bytes = format.serialize(eventOf("hello", "world"));
+
+    Object[] message = format.deserialize(bytes);
+
+    assertThat(asList(message), contains("hello", "world"));
+  }
+
+  @Test
+  public void blowsUpWhenObjectIsNotSerializable() throws Exception {
+    try {
+      format.serialize(eventOf(new NotSerializable()));
+      expectFailing(OmegaException.class);
+    } catch (OmegaException e) {
+      assertThat(e.getMessage(), startsWith("Unable to serialize event with global tx id"));
+    }
+  }
+
+  @Test
+  public void blowsUpWhenObjectIsNotDeserializable() throws Exception {
+    try {
+      format.deserialize(new byte[0]);
+      expectFailing(OmegaException.class);
+    } catch (OmegaException e) {
+      assertThat(e.getMessage(), startsWith("Unable to deserialize message"));
+    }
+  }
+
+  private TxEvent eventOf(Object... payloads) {
+    return new TxEvent(null, null, null, payloads);
+  }
+
+  private static class NotSerializable {
+  }
+}
\ No newline at end of file
diff --git a/omega/pom.xml b/omega/omega-spring-starter/pom.xml
similarity index 54%
copy from omega/pom.xml
copy to omega/omega-spring-starter/pom.xml
index ac4e397..b900a47 100644
--- a/omega/pom.xml
+++ b/omega/omega-spring-starter/pom.xml
@@ -20,42 +20,31 @@
   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>saga</artifactId>
+    <artifactId>omega</artifactId>
     <groupId>io.servicecomb.saga</groupId>
     <version>0.0.3-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
-  <artifactId>omega</artifactId>
-  <packaging>pom</packaging>
-  <modules>
-    <module>omega-transaction</module>
-    <module>omega-context</module>
-    <module>omega-spring-tx</module>
-    <module>omega-transport</module>
-    <module>omega-connector</module>
-  </modules>
+  <artifactId>omega-spring-starter</artifactId>
 
-  <dependencyManagement>
-    <dependencies>
-      <dependency>
-        <groupId>org.springframework.boot</groupId>
-        <artifactId>spring-boot-dependencies</artifactId>
-        <version>${spring.boot.version}</version>
-        <type>pom</type>
-        <scope>import</scope>
-      </dependency>
-      <dependency>
-        <groupId>io.servicecomb.saga</groupId>
-        <artifactId>omega-context</artifactId>
-        <version>0.0.3-SNAPSHOT</version>
-      </dependency>
-      <dependency>
-        <groupId>io.servicecomb.saga</groupId>
-        <artifactId>omega-transaction</artifactId>
-        <version>0.0.3-SNAPSHOT</version>
-      </dependency>
-    </dependencies>
-  </dependencyManagement>
+  <dependencies>
+    <dependency>
+      <groupId>io.servicecomb.saga</groupId>
+      <artifactId>omega-transport-resttemplate</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.servicecomb.saga</groupId>
+      <artifactId>omega-spring-tx</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.servicecomb.saga</groupId>
+      <artifactId>omega-connector-thrift</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.servicecomb.saga</groupId>
+      <artifactId>omega-format</artifactId>
+    </dependency>
+  </dependencies>
 
-</project>
\ No newline at end of file
+</project>
diff --git a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java b/omega/omega-spring-starter/src/main/java/io/servicecomb/saga/omega/spring/EnableOmega.java
similarity index 61%
copy from omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java
copy to omega/omega-spring-starter/src/main/java/io/servicecomb/saga/omega/spring/EnableOmega.java
index d4315b3..8d5f851 100644
--- a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java
+++ b/omega/omega-spring-starter/src/main/java/io/servicecomb/saga/omega/spring/EnableOmega.java
@@ -15,8 +15,19 @@
  * limitations under the License.
  */
 
-package io.servicecomb.saga.omega.transaction;
+package io.servicecomb.saga.omega.spring;
 
-public interface MessageDeserializer {
-  <T> T deserialize(byte[] message);
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.context.annotation.Import;
+
+import io.servicecomb.saga.omega.transaction.spring.TransactionAspectConfig;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Import({OmegaSpringConfig.class, TransactionAspectConfig.class})
+public @interface EnableOmega {
 }
diff --git a/omega/omega-spring-starter/src/main/java/io/servicecomb/saga/omega/spring/OmegaSpringConfig.java b/omega/omega-spring-starter/src/main/java/io/servicecomb/saga/omega/spring/OmegaSpringConfig.java
new file mode 100644
index 0000000..ae92123
--- /dev/null
+++ b/omega/omega-spring-starter/src/main/java/io/servicecomb/saga/omega/spring/OmegaSpringConfig.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.servicecomb.saga.omega.spring;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Arrays;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import io.servicecomb.saga.omega.connector.thrift.ThriftMessageSender;
+import io.servicecomb.saga.omega.format.NativeMessageFormat;
+import io.servicecomb.saga.omega.transaction.MessageSender;
+
+@Configuration
+class OmegaSpringConfig {
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  @Bean
+  MessageSender messageSender(@Value("${alpha.cluster.address}") String[] addresses) {
+    // TODO: 2017/12/26 connect to the one with lowest latency
+    for (String address : addresses) {
+      try {
+        String[] pair = address.split(":");
+        return ThriftMessageSender.create(pair[0], Integer.parseInt(pair[1]), new NativeMessageFormat());
+      } catch (Exception e) {
+        log.error("Unable to connect to alpha at {}", address, e);
+      }
+    }
+
+    throw new IllegalArgumentException(
+        "None of the alpha cluster is reachable: " + Arrays.toString(addresses));
+  }
+}
diff --git a/omega/omega-spring-tx/src/main/java/io/servicecomb/saga/omega/transaction/spring/CompensableMethodCheckingCallback.java b/omega/omega-spring-tx/src/main/java/io/servicecomb/saga/omega/transaction/spring/CompensableMethodCheckingCallback.java
index c29061c..23352f4 100644
--- a/omega/omega-spring-tx/src/main/java/io/servicecomb/saga/omega/transaction/spring/CompensableMethodCheckingCallback.java
+++ b/omega/omega-spring-tx/src/main/java/io/servicecomb/saga/omega/transaction/spring/CompensableMethodCheckingCallback.java
@@ -24,6 +24,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.util.ReflectionUtils.MethodCallback;
 
+import io.servicecomb.saga.omega.transaction.OmegaException;
 import io.servicecomb.saga.omega.transaction.annotations.Compensable;
 
 class CompensableMethodCheckingCallback implements MethodCallback {
@@ -47,7 +48,7 @@ class CompensableMethodCheckingCallback implements MethodCallback {
       bean.getClass().getDeclaredMethod(compensationMethod, method.getParameterTypes());
       LOG.debug("Found compensation method [{}] in {}", compensationMethod, bean.getClass().getCanonicalName());
     } catch (NoSuchMethodException e) {
-      throw new IllegalArgumentException(
+      throw new OmegaException(
           "No such compensation method [" + compensationMethod + "] found in " + bean.getClass().getCanonicalName(),
           e);
     }
diff --git a/omega/omega-spring-tx/src/main/java/io/servicecomb/saga/omega/transaction/spring/TransactionAspectConfig.java b/omega/omega-spring-tx/src/main/java/io/servicecomb/saga/omega/transaction/spring/TransactionAspectConfig.java
index f44e66f..59f7d2e 100644
--- a/omega/omega-spring-tx/src/main/java/io/servicecomb/saga/omega/transaction/spring/TransactionAspectConfig.java
+++ b/omega/omega-spring-tx/src/main/java/io/servicecomb/saga/omega/transaction/spring/TransactionAspectConfig.java
@@ -27,7 +27,7 @@ import io.servicecomb.saga.omega.transaction.TransactionAspect;
 
 @Configuration
 @EnableAspectJAutoProxy
-class TransactionAspectConfig {
+public class TransactionAspectConfig {
   @Bean
   OmegaContext omegaContext() {
     return new OmegaContext();
diff --git a/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/CompensableAnnotationCheckingTest.java b/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/CompensableAnnotationCheckingTest.java
index e83a621..29698a0 100644
--- a/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/CompensableAnnotationCheckingTest.java
+++ b/omega/omega-spring-tx/src/test/java/io/servicecomb/saga/omega/transaction/spring/CompensableAnnotationCheckingTest.java
@@ -33,7 +33,7 @@ public class CompensableAnnotationCheckingTest {
       try (ConfigurableApplicationContext ignored = new SpringApplicationBuilder(TransactionTestMain.class)
           .profiles("annotation-checking")
           .run()) {
-        expectFailing(IllegalArgumentException.class);
+        expectFailing(BeanCreationException.class);
       }
     } catch (BeanCreationException e) {
       assertThat(e.getCause().getMessage(), startsWith("No such compensation method [none]"));
diff --git a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java
index d4315b3..e5348f4 100644
--- a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java
+++ b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java
@@ -18,5 +18,5 @@
 package io.servicecomb.saga.omega.transaction;
 
 public interface MessageDeserializer {
-  <T> T deserialize(byte[] message);
+  Object[] deserialize(byte[] message);
 }
diff --git a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/OmegaException.java
similarity index 85%
copy from omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java
copy to omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/OmegaException.java
index d4315b3..a67b2ce 100644
--- a/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/MessageDeserializer.java
+++ b/omega/omega-transaction/src/main/java/io/servicecomb/saga/omega/transaction/OmegaException.java
@@ -17,6 +17,9 @@
 
 package io.servicecomb.saga.omega.transaction;
 
-public interface MessageDeserializer {
-  <T> T deserialize(byte[] message);
+public class OmegaException extends RuntimeException {
+
+  public OmegaException(String cause, Throwable throwable) {
+    super(cause, throwable);
+  }
 }
diff --git a/omega/pom.xml b/omega/pom.xml
index ac4e397..a0def30 100644
--- a/omega/pom.xml
+++ b/omega/pom.xml
@@ -34,6 +34,8 @@
     <module>omega-spring-tx</module>
     <module>omega-transport</module>
     <module>omega-connector</module>
+    <module>omega-spring-starter</module>
+    <module>omega-format</module>
   </modules>
 
   <dependencyManagement>
diff --git a/pom.xml b/pom.xml
index 026d3df..6668b59 100755
--- a/pom.xml
+++ b/pom.xml
@@ -26,7 +26,6 @@
 
   <modules>
     <module>saga-core</module>
-    <module>integration-tests</module>
     <module>transports</module>
     <module>saga-spring</module>
     <module>docker-build-config</module>
@@ -36,6 +35,7 @@
     <module>omega</module>
     <module>alpha</module>
     <module>pack-contracts</module>
+    <module>integration-tests</module>
   </modules>
 
   <properties>
@@ -50,6 +50,7 @@
     <spring.version>4.3.7.RELEASE</spring.version>
     <akka.version>2.5.6</akka.version>
     <rat.version>0.12</rat.version>
+    <maven.failsafe.version>2.19.1</maven.failsafe.version>
   </properties>
 
   <name>ServiceComb Saga</name>
@@ -152,11 +153,31 @@
       </dependency>
       <dependency>
         <groupId>io.servicecomb.saga</groupId>
+        <artifactId>omega-connector-thrift</artifactId>
+        <version>0.0.3-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>io.servicecomb.saga</groupId>
+        <artifactId>omega-spring-starter</artifactId>
+        <version>0.0.3-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>io.servicecomb.saga</groupId>
+        <artifactId>omega-format</artifactId>
+        <version>0.0.3-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>io.servicecomb.saga</groupId>
         <artifactId>alpha-core</artifactId>
         <version>0.0.3-SNAPSHOT</version>
       </dependency>
       <dependency>
         <groupId>io.servicecomb.saga</groupId>
+        <artifactId>alpha-server</artifactId>
+        <version>0.0.3-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>io.servicecomb.saga</groupId>
         <artifactId>pack-contract-thrift</artifactId>
         <version>0.0.3-SNAPSHOT</version>
       </dependency>
@@ -294,6 +315,10 @@
             <groupId>javax.validation</groupId>
             <artifactId>validation-api</artifactId>
           </exclusion>
+          <exclusion>
+            <groupId>org.apache.bval</groupId>
+            <artifactId>bval-jsr303</artifactId>
+          </exclusion>
         </exclusions>
       </dependency>
 
diff --git a/saga-demo/conditional-transaction-demo/conditional-transaction-demo-tests/pom.xml b/saga-demo/conditional-transaction-demo/conditional-transaction-demo-tests/pom.xml
index f1a5bba..a037c14 100644
--- a/saga-demo/conditional-transaction-demo/conditional-transaction-demo-tests/pom.xml
+++ b/saga-demo/conditional-transaction-demo/conditional-transaction-demo-tests/pom.xml
@@ -250,7 +250,7 @@
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-failsafe-plugin</artifactId>
-            <version>2.19.1</version>
+            <version>${maven.failsafe.version}</version>
             <configuration>
               <systemPropertyVariables>
                 <saga.address>
diff --git a/saga-demo/dependency-free-transaction-demo/demo-tests/pom.xml b/saga-demo/dependency-free-transaction-demo/demo-tests/pom.xml
index 6684628..80568fd 100644
--- a/saga-demo/dependency-free-transaction-demo/demo-tests/pom.xml
+++ b/saga-demo/dependency-free-transaction-demo/demo-tests/pom.xml
@@ -282,7 +282,7 @@
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-failsafe-plugin</artifactId>
-            <version>2.19.1</version>
+            <version>${maven.failsafe.version}</version>
             <configuration>
               <systemPropertyVariables>
                 <saga.address>

-- 
To stop receiving notification emails like this one, please contact
"commits@servicecomb.apache.org" <co...@servicecomb.apache.org>.