You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by di...@apache.org on 2019/01/17 13:20:06 UTC

[rocketmq-spring] branch master updated (267ab40 -> c21077c)

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

dinglei pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git.


 discard 267ab40  [maven-release-plugin] prepare for next development iteration
 discard 6db552f  [maven-release-plugin] prepare release rocketmq-spring-boot-build-2.0.1
     new c21077c  Revert RocketMQ Spring Version

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (267ab40)
            \
             N -- N -- N   refs/heads/master (c21077c)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 37 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:


[rocketmq-spring] 16/37: Make version as 2.0.0-SNAPSHOT at the public review phase

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit b19dbf9e48387cc03c3aeed60a37162b62079fd5
Merge: 5e7ed27 e895eec
Author: walking98 <wi...@gmail.com>
AuthorDate: Fri Dec 14 16:13:28 2018 +0800

    Make version as 2.0.0-SNAPSHOT at the public review phase

 README.md                                            | 18 +++++++++---------
 README_zh_CN.md                                      | 18 +++++++++---------
 pom.xml                                              |  2 +-
 rocketmq-spring-boot-parent/pom.xml                  |  2 +-
 rocketmq-spring-boot-samples/pom.xml                 |  2 +-
 rocketmq-spring-boot-starter/pom.xml                 |  2 +-
 rocketmq-spring-boot/pom.xml                         |  2 +-
 .../rocketmq/spring/annotation/MessageModel.java     |  2 +-
 .../config/ListenerContainerConfiguration.java       |  7 ++-----
 .../spring/config/RocketMQAutoConfiguration.java     | 20 +++++++++++++-------
 .../spring/config/RocketMQAutoConfigurationTest.java |  4 ++--
 11 files changed, 41 insertions(+), 38 deletions(-)

diff --cc README.md
index d916346,89ac93e..fa5beeb
--- a/README.md
+++ b/README.md
@@@ -39,7 -39,7 +39,7 @@@ We are always very happy to have contri
  
  Please see the complete sample [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples)
  
- Note: Current RELEASE.VERSION=2.0.1
 -Note: Current RELEASE.VERSION=2.0.0
++Note: Current RELEASE.VERSION=2.0.0-SNAPSHOT
  
  ```xml
  <!--add dependency in pom.xml-->
@@@ -54,7 -54,7 +54,7 @@@
  
  ```properties
  ## application.properties
--spring.rocketmq.nameServer=127.0.0.1:9876
++spring.rocketmq.name-server=127.0.0.1:9876
  spring.rocketmq.producer.group=my-group
  ```
  
@@@ -93,12 -93,12 +93,12 @@@ public class ProducerApplication implem
  > More relevant configurations for producing:
  >
  > ```properties
--> spring.rocketmq.producer.retryTimesWhenSendAsyncFailed=0
--> spring.rocketmq.producer.sendMessageTimeout=300000
--> spring.rocketmq.producer.compressMessageBodyOverHowmuch=4096
--> spring.rocketmq.producer.maxMessageSize=4194304
--> spring.rocketmq.producer.retryAnotherBrokerWhenNotStoreOk=false
--> spring.rocketmq.producer.retryTimesWhenSendFailed=2
++> spring.rocketmq.producer.retry-times-when-send-async-failed=0
++> spring.rocketmq.producer.send-message-timeout=300000
++> spring.rocketmq.producer.compress-message-body-threshold=4096
++> spring.rocketmq.producer.max-message-size=4194304
++> spring.rocketmq.producer.retry-another-broker-when-not-store-ok=false
++> spring.rocketmq.producer.retry-times-when-send-failed=2
  > ```
  
  
@@@ -147,7 -147,7 +147,7 @@@ public class ProducerApplication implem
  
  ```properties
  ## application.properties
--spring.rocketmq.nameServer=127.0.0.1:9876
++spring.rocketmq.name-server=127.0.0.1:9876
  ```
  
  > Note:
diff --cc README_zh_CN.md
index 0836703,168230d..6c2a074
--- a/README_zh_CN.md
+++ b/README_zh_CN.md
@@@ -30,7 -30,7 +30,7 @@@
  
  下面列出来了一些关键点,完整的示例请参考: [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples)
  
- 注意:当前的RELEASE.VERSION=2.0.1
 -注意:当前的RELEASE.VERSION=2.0.0
++注意:当前的RELEASE.VERSION=2.0.0-SNAPSHOT
  
  ```xml
  <!--在pom.xml中添加依赖-->
@@@ -45,7 -45,7 +45,7 @@@
  
  ```properties
  ## application.properties
--spring.rocketmq.nameServer=127.0.0.1:9876
++spring.rocketmq.name-server=127.0.0.1:9876
  spring.rocketmq.producer.group=my-group
  ```
  
@@@ -125,12 -125,12 +125,12 @@@ public class ProducerApplication implem
  > 更多发送相关配置
  >
  > ```properties
--> spring.rocketmq.producer.retryTimesWhenSendAsyncFailed=0
--> spring.rocketmq.producer.sendMessageTimeout=300000
--> spring.rocketmq.producer.compressMessageBodyOverHowmuch=4096
--> spring.rocketmq.producer.maxMessageSize=4194304
--> spring.rocketmq.producer.retryAnotherBrokerWhenNotStoreOk=false
--> spring.rocketmq.producer.retryTimesWhenSendFailed=2
++> spring.rocketmq.producer.retry-times-when-send-async-failed=0
++> spring.rocketmq.producer.send-message-timeout=300000
++> spring.rocketmq.producer.compress-message-body-threshold=4096
++> spring.rocketmq.producer.max-message-size=4194304
++> spring.rocketmq.producer.retry-another-broker-when-not-store-ok=false
++> spring.rocketmq.producer.retry-times-when-send-failed=2
  > ```
  
  
@@@ -138,7 -138,7 +138,7 @@@
  
  ```properties
  ## application.properties
--spring.rocketmq.nameServer=127.0.0.1:9876
++spring.rocketmq.name-server=127.0.0.1:9876
  ```
  
  > 注意:
diff --cc pom.xml
index a09e012,7ca40cc..7212b4b
--- a/pom.xml
+++ b/pom.xml
@@@ -22,7 -22,7 +22,7 @@@
  
      <groupId>org.apache.rocketmq</groupId>
      <artifactId>rocketmq-spring-boot-build</artifactId>
-     <version>2.0.1</version>
 -    <version>2.0.0</version>
++    <version>2.0.0-SNAPSHOT</version>
      <packaging>pom</packaging>
  
      <name>RocketMQ Spring Boot Build</name>
diff --cc rocketmq-spring-boot-parent/pom.xml
index 638a0d4,005c2cb..cbeea37
--- a/rocketmq-spring-boot-parent/pom.xml
+++ b/rocketmq-spring-boot-parent/pom.xml
@@@ -23,7 -23,7 +23,7 @@@
      <parent>
          <groupId>org.apache.rocketmq</groupId>
          <artifactId>rocketmq-spring-boot-build</artifactId>
-         <version>2.0.1</version>
 -        <version>2.0.0</version>
++        <version>2.0.0-SNAPSHOT</version>
          <relativePath>../pom.xml</relativePath>
      </parent>
  
diff --cc rocketmq-spring-boot-samples/pom.xml
index c1699b6,7b5eaa5..838268a
--- a/rocketmq-spring-boot-samples/pom.xml
+++ b/rocketmq-spring-boot-samples/pom.xml
@@@ -36,7 -36,7 +36,7 @@@
      </modules>
  
      <properties>
-         <rocketmq-spring-boot-starter-version>2.0.1</rocketmq-spring-boot-starter-version>
 -        <rocketmq-spring-boot-starter-version>2.0.0</rocketmq-spring-boot-starter-version>
++        <rocketmq-spring-boot-starter-version>2.0.0-SNAPSHOT</rocketmq-spring-boot-starter-version>
      </properties>
  
      <dependencies>
diff --cc rocketmq-spring-boot-starter/pom.xml
index 325fcc9,cd88b71..ff9d16a
--- a/rocketmq-spring-boot-starter/pom.xml
+++ b/rocketmq-spring-boot-starter/pom.xml
@@@ -23,7 -23,7 +23,7 @@@
      <parent>
          <groupId>org.apache.rocketmq</groupId>
          <artifactId>rocketmq-spring-boot-parent</artifactId>
-         <version>2.0.1</version>
 -        <version>2.0.0</version>
++        <version>2.0.0-SNAPSHOT</version>
          <relativePath>../rocketmq-spring-boot-parent/pom.xml</relativePath>
      </parent>
  
diff --cc rocketmq-spring-boot/pom.xml
index 6a7b687,94e528c..67f0f4c
--- a/rocketmq-spring-boot/pom.xml
+++ b/rocketmq-spring-boot/pom.xml
@@@ -23,7 -23,7 +23,7 @@@
      <parent>
          <groupId>org.apache.rocketmq</groupId>
          <artifactId>rocketmq-spring-boot-parent</artifactId>
-         <version>2.0.1</version>
 -        <version>2.0.0</version>
++        <version>2.0.0-SNAPSHOT</version>
          <relativePath>../rocketmq-spring-boot-parent/pom.xml</relativePath>
      </parent>
  
diff --cc rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
index bd7cda1,5eb97a5..b65dee1
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
@@@ -98,8 -91,20 +91,21 @@@ public class RocketMQAutoConfiguration 
      @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME)
      @ConditionalOnBean(TransactionHandlerRegistry.class)
      @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 -    public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor(TransactionHandlerRegistry transactionHandlerRegistry) {
 +    public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor(
 +        TransactionHandlerRegistry transactionHandlerRegistry) {
          return new RocketMQTransactionAnnotationProcessor(transactionHandlerRegistry);
      }
+ 
+     @Configuration
+     @ConditionalOnClass(ObjectMapper.class)
+     static class JacksonConfiguration {
+ 
+         @Bean
+         @ConditionalOnMissingBean(ObjectMapper.class)
+         public ObjectMapper rocketMQMessageObjectMapper() {
+             return new ObjectMapper();
+         }
+ 
+     }
+ 
  }
diff --cc rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
index 2656249,fd4056f..c0fa370
--- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
+++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
@@@ -48,8 -48,8 +48,8 @@@ public class RocketMQAutoConfigurationT
  
  
      @Test
 -    public void testDefaultMQProducer() {
 -        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876",
 +    public void testDefaultMQProducerWithRelaxPropertyName() {
-         runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876",
++        runner.withPropertyValues("spring.rocketmq.nameServer=127.0.0.1:9876",
                  "spring.rocketmq.producer.group=spring_rocketmq").
                  run((context) -> {
                      assertThat(context).hasSingleBean(DefaultMQProducer.class);
@@@ -59,16 -59,6 +59,16 @@@
      }
  
      @Test
 +    public void testDefaultMQProducer() {
-         runner.withPropertyValues("spring.rocketmq.nameServer=127.0.0.1:9876",
++        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876",
 +            "spring.rocketmq.producer.group=spring_rocketmq").
 +            run((context) -> {
 +                assertThat(context).hasSingleBean(DefaultMQProducer.class);
 +            });
 +
 +    }
 +
 +    @Test
      public void testRocketMQListenerContainer() {
          runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876").
              withUserConfiguration(TestConfig.class).


[rocketmq-spring] 01/37: First commit

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 6302fcabf92ed99b376a121421dbc369826f8e07
Author: vongosling <vo...@apache.org>
AuthorDate: Thu Dec 6 16:44:26 2018 +0800

    First commit
---
 README.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1ce682f
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# rocketmq-spring


[rocketmq-spring] 08/37: Update README.md

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit c53cbb51bd05d0b57bec7a9dfa92a9fade909cb8
Author: von gosling <vo...@apache.org>
AuthorDate: Fri Dec 7 12:35:41 2018 +0800

    Update README.md
---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 50c0b3b..37e9f83 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# rocketmq-spring-boot
+# Rocketmq-Spring
 
 [中文](./README_zh_CN.md)
 


[rocketmq-spring] 13/37: Bump up version to 2.0.1

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 5e7ed27835478fc19d2d30640c02971adbc3cf73
Author: walking98 <wi...@gmail.com>
AuthorDate: Wed Dec 12 11:38:48 2018 +0800

    Bump up version to 2.0.1
---
 README.md                            | 2 +-
 README_zh_CN.md                      | 2 +-
 pom.xml                              | 2 +-
 rocketmq-spring-boot-parent/pom.xml  | 4 ++--
 rocketmq-spring-boot-samples/pom.xml | 2 +-
 rocketmq-spring-boot-starter/pom.xml | 2 +-
 rocketmq-spring-boot/pom.xml         | 2 +-
 7 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 89ac93e..d916346 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ We are always very happy to have contributions, whether for trivial cleanups or
 
 Please see the complete sample [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples)
 
-Note: Current RELEASE.VERSION=2.0.0
+Note: Current RELEASE.VERSION=2.0.1
 
 ```xml
 <!--add dependency in pom.xml-->
diff --git a/README_zh_CN.md b/README_zh_CN.md
index 168230d..0836703 100644
--- a/README_zh_CN.md
+++ b/README_zh_CN.md
@@ -30,7 +30,7 @@
 
 下面列出来了一些关键点,完整的示例请参考: [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples)
 
-注意:当前的RELEASE.VERSION=2.0.0
+注意:当前的RELEASE.VERSION=2.0.1
 
 ```xml
 <!--在pom.xml中添加依赖-->
diff --git a/pom.xml b/pom.xml
index 7ca40cc..a09e012 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
 
     <groupId>org.apache.rocketmq</groupId>
     <artifactId>rocketmq-spring-boot-build</artifactId>
-    <version>2.0.0</version>
+    <version>2.0.1</version>
     <packaging>pom</packaging>
 
     <name>RocketMQ Spring Boot Build</name>
diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml
index 005c2cb..638a0d4 100644
--- a/rocketmq-spring-boot-parent/pom.xml
+++ b/rocketmq-spring-boot-parent/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.apache.rocketmq</groupId>
         <artifactId>rocketmq-spring-boot-build</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.1</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
@@ -39,7 +39,7 @@
         <spring.boot.version>2.0.5.RELEASE</spring.boot.version>
         <spring.version>5.1.0.RELEASE</spring.version>
 
-        <rocketmq.spring.boot.version>2.0.0</rocketmq.spring.boot.version>
+        <rocketmq.spring.boot.version>${project.version}</rocketmq.spring.boot.version>
 
         <rocketmq-version>4.3.2</rocketmq-version>
         <slf4j.version>1.6.1</slf4j.version>
diff --git a/rocketmq-spring-boot-samples/pom.xml b/rocketmq-spring-boot-samples/pom.xml
index 7b5eaa5..c1699b6 100644
--- a/rocketmq-spring-boot-samples/pom.xml
+++ b/rocketmq-spring-boot-samples/pom.xml
@@ -36,7 +36,7 @@
     </modules>
 
     <properties>
-        <rocketmq-spring-boot-starter-version>2.0.0</rocketmq-spring-boot-starter-version>
+        <rocketmq-spring-boot-starter-version>2.0.1</rocketmq-spring-boot-starter-version>
     </properties>
 
     <dependencies>
diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml
index cd88b71..325fcc9 100644
--- a/rocketmq-spring-boot-starter/pom.xml
+++ b/rocketmq-spring-boot-starter/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.apache.rocketmq</groupId>
         <artifactId>rocketmq-spring-boot-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.1</version>
         <relativePath>../rocketmq-spring-boot-parent/pom.xml</relativePath>
     </parent>
 
diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml
index 94e528c..6a7b687 100644
--- a/rocketmq-spring-boot/pom.xml
+++ b/rocketmq-spring-boot/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.apache.rocketmq</groupId>
         <artifactId>rocketmq-spring-boot-parent</artifactId>
-        <version>2.0.0</version>
+        <version>2.0.1</version>
         <relativePath>../rocketmq-spring-boot-parent/pom.xml</relativePath>
     </parent>
 


[rocketmq-spring] 31/37: Adjust config property name RetryAnotherBrokerWhenNotStoreOK -> retryNextServer

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 0abbd0b632eefeb9be56727c008372f9170debda
Author: walking98 <wi...@gmail.com>
AuthorDate: Wed Dec 19 15:52:40 2018 +0800

    Adjust config property name RetryAnotherBrokerWhenNotStoreOK  -> retryNextServer
---
 README.md                                                      |  4 ++--
 README_zh_CN.md                                                |  4 ++--
 .../rocketmq/spring/config/RocketMQAutoConfiguration.java      |  2 +-
 .../org/apache/rocketmq/spring/config/RocketMQProperties.java  | 10 +++++-----
 .../rocketmq/spring/config/RocketMQAutoConfigurationTest.java  |  4 ++--
 5 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md
index 9f42552..37264c3 100644
--- a/README.md
+++ b/README.md
@@ -93,11 +93,11 @@ public class ProducerApplication implements CommandLineRunner{
 > More relevant configurations for producing:
 >
 > ```properties
-> rocketmq.producer.retry-times-when-send-async-failed=0
 > rocketmq.producer.send-message-timeout=300000
 > rocketmq.producer.compress-message-body-threshold=4096
 > rocketmq.producer.max-message-size=4194304
-> rocketmq.producer.retry-another-broker-when-not-store-ok=false
+> rocketmq.producer.retry-times-when-send-async-failed=0
+> rocketmq.producer.retry-next-server=true
 > rocketmq.producer.retry-times-when-send-failed=2
 > ```
 
diff --git a/README_zh_CN.md b/README_zh_CN.md
index 82bb24e..a150e75 100644
--- a/README_zh_CN.md
+++ b/README_zh_CN.md
@@ -125,11 +125,11 @@ public class ProducerApplication implements CommandLineRunner{
 > 更多发送相关配置
 >
 > ```properties
-> rocketmq.producer.retry-times-when-send-async-failed=0
 > rocketmq.producer.send-message-timeout=300000
 > rocketmq.producer.compress-message-body-threshold=4096
 > rocketmq.producer.max-message-size=4194304
-> rocketmq.producer.retry-another-broker-when-not-store-ok=false
+> rocketmq.producer.retry-times-when-send-async-failed=0
+> rocketmq.producer.retry-next-server=true
 > rocketmq.producer.retry-times-when-send-failed=2
 > ```
 
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
index c031335..ee35f81 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
@@ -60,7 +60,7 @@ public class RocketMQAutoConfiguration {
         producer.setRetryTimesWhenSendAsyncFailed(producerConfig.getRetryTimesWhenSendAsyncFailed());
         producer.setMaxMessageSize(producerConfig.getMaxMessageSize());
         producer.setCompressMsgBodyOverHowmuch(producerConfig.getCompressMessageBodyThreshold());
-        producer.setRetryAnotherBrokerWhenNotStoreOK(producerConfig.isRetryAnotherBrokerWhenNotStoreOk());
+        producer.setRetryAnotherBrokerWhenNotStoreOK(producerConfig.isRetryNextServer());
 
         return producer;
     }
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
index 9c8ce89..778ba77 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
@@ -78,7 +78,7 @@ public class RocketMQProperties {
         /**
          * Indicate whether to retry another broker on sending failure internally.
          */
-        private boolean retryAnotherBrokerWhenNotStoreOk = false;
+        private boolean retryNextServer = false;
 
         /**
          * Maximum allowed message size in bytes.
@@ -125,12 +125,12 @@ public class RocketMQProperties {
             this.retryTimesWhenSendAsyncFailed = retryTimesWhenSendAsyncFailed;
         }
 
-        public boolean isRetryAnotherBrokerWhenNotStoreOk() {
-            return retryAnotherBrokerWhenNotStoreOk;
+        public boolean isRetryNextServer() {
+            return retryNextServer;
         }
 
-        public void setRetryAnotherBrokerWhenNotStoreOk(boolean retryAnotherBrokerWhenNotStoreOk) {
-            this.retryAnotherBrokerWhenNotStoreOk = retryAnotherBrokerWhenNotStoreOk;
+        public void setRetryNextServer(boolean retryNextServer) {
+            this.retryNextServer = retryNextServer;
         }
 
         public int getMaxMessageSize() {
diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
index c3e2d00..c719e8c 100644
--- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
+++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
@@ -84,7 +84,7 @@ public class RocketMQAutoConfigurationTest {
 
     @Test
     public void testRocketMQListenerWithCustomObjectMapper() {
-        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876").
+        runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876").
                 withUserConfiguration(TestConfig.class, CustomObjectMapperConfig.class).
                 run((context) -> {
                     assertThat(context).hasSingleBean(DefaultRocketMQListenerContainer.class);
@@ -95,7 +95,7 @@ public class RocketMQAutoConfigurationTest {
 
     @Test
     public void testRocketMQListenerWithSeveralObjectMappers() {
-        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876").
+        runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876").
                 withUserConfiguration(TestConfig.class, CustomObjectMappersConfig.class).
                 run((context) -> {
                     assertThat(context).hasSingleBean(DefaultRocketMQListenerContainer.class);


[rocketmq-spring] 03/37: Add github template

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 0e777d237f85a46dd5d610d75ea545deb140a673
Author: walking98 <wi...@gmail.com>
AuthorDate: Thu Dec 6 17:06:26 2018 +0800

    Add github template
---
 .github/ISSUE_TEMPLATE.md        | 31 +++++++++++++++++++++++++++++++
 .github/PULL_REQUEST_TEMPLATE.md | 20 ++++++++++++++++++++
 2 files changed, 51 insertions(+)

diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..2cd7924
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,31 @@
+The issue tracker is **ONLY** used for bug report and feature request. 
+
+Any question or RocketMQ proposal please use our [mailing lists](http://rocketmq.apache.org/about/contact/).
+
+**BUG REPORT**
+
+1. Please describe the issue you observed:
+
+- What did you do (The steps to reproduce)?
+
+- What did you expect to see?
+
+- What did you see instead?
+
+2. Please tell us about your environment:
+
+3. Other information (e.g. detailed explanation, logs, related issues, suggestions how to fix, etc):
+
+**FEATURE REQUEST**
+
+1. Please describe the feature you are requesting.
+
+2. Provide any additional detail on your proposed use case for this feature.
+
+2. Indicate the importance of this issue to you (blocker, must-have, should-have, nice-to-have). Are you currently using any workarounds to address this issue?
+
+4. If there are some sub-tasks using -[] for each subtask and create a corresponding issue to map to the sub task:
+
+- [sub-task1-issue-number](example_sub_issue1_link_here): sub-task1 description here, 
+- [sub-task2-issue-number](example_sub_issue2_link_here): sub-task2 description here,
+- ...
\ No newline at end of file
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..143dac8
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,20 @@
+## What is the purpose of the change
+
+XXXXX
+
+## Brief changelog
+
+XX
+
+## Verifying this change
+
+XXXX
+
+Follow this checklist to help us incorporate your contribution quickly and easily. Notice, `it would be helpful if you could finish the following 5 checklist(the last one is not necessary)before request the community to review your PR`.
+
+- [x] Make sure there is a [Github issue](https://github.com/apache/rocketmq/issues) filed for the change (usually before you start working on it). Trivial changes like typos do not require a Github issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue. 
+- [x] Format the pull request title like `[ISSUE #123] Fix UnknownException when host config not exist`. Each commit in the pull request should have a meaningful subject line and body.
+- [x] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
+- [x] Write necessary unit-test(over 80% coverage) to verify your logic correction, more mock a little better when cross module dependency exist. If the new feature or significant change is committed, please remember to add integration-test in [test module](https://github.com/apache/rocketmq/tree/master/test).
+- [x] Run `mvn -B clean apache-rat:check findbugs:findbugs checkstyle:checkstyle` to make sure basic checks pass. Run `mvn clean install -DskipITs` to make sure unit-test pass. Run `mvn clean test-compile failsafe:integration-test`  to make sure integration-test pass.
+- [ ] If this contribution is large, please file an [Apache Individual Contributor License Agreement](http://www.apache.org/licenses/#clas).


[rocketmq-spring] 34/37: Polish

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 34388b86d23c3d5a9b3bff059cb01112aa1bba36
Author: Stephane Nicoll <sn...@pivotal.io>
AuthorDate: Fri Dec 21 16:31:38 2018 +0100

    Polish
---
 .../{config => autoconfigure}/JacksonFallbackConfiguration.java      | 2 +-
 .../{config => autoconfigure}/ListenerContainerConfiguration.java    | 4 ++--
 .../spring/{config => autoconfigure}/RocketMQAutoConfiguration.java  | 5 ++++-
 .../spring/{config => autoconfigure}/RocketMQProperties.java         | 2 +-
 rocketmq-spring-boot/src/main/resources/META-INF/spring.factories    | 2 +-
 .../{config => autoconfigure}/RocketMQAutoConfigurationTest.java     | 2 +-
 6 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/JacksonFallbackConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java
similarity index 96%
rename from rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/JacksonFallbackConfiguration.java
rename to rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java
index a66887a..d25ca8d 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/JacksonFallbackConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.rocketmq.spring.config;
+package org.apache.rocketmq.spring.autoconfigure;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java
similarity index 97%
rename from rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
rename to rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java
index 506369e..da66132 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.rocketmq.spring.config;
+package org.apache.rocketmq.spring.autoconfigure;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.rocketmq.spring.annotation.ConsumeMode;
@@ -43,7 +43,7 @@ import java.util.concurrent.atomic.AtomicLong;
 
 @Configuration
 public class ListenerContainerConfiguration implements ApplicationContextAware, SmartInitializingSingleton {
-    private final static Logger log = LoggerFactory.getLogger(RocketMQAutoConfiguration.class);
+    private final static Logger log = LoggerFactory.getLogger(ListenerContainerConfiguration.class);
 
     private ConfigurableApplicationContext applicationContext;
 
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java
similarity index 94%
rename from rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
rename to rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java
index ee35f81..78a6eba 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java
@@ -15,11 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.rocketmq.spring.config;
+package org.apache.rocketmq.spring.autoconfigure;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.rocketmq.client.MQAdmin;
 import org.apache.rocketmq.client.producer.DefaultMQProducer;
+import org.apache.rocketmq.spring.config.RocketMQConfigUtils;
+import org.apache.rocketmq.spring.config.RocketMQTransactionAnnotationProcessor;
+import org.apache.rocketmq.spring.config.TransactionHandlerRegistry;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.boot.autoconfigure.AutoConfigureAfter;
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java
similarity index 98%
rename from rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
rename to rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java
index 778ba77..88495e5 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.rocketmq.spring.config;
+package org.apache.rocketmq.spring.autoconfigure;
 
 import org.springframework.boot.context.properties.ConfigurationProperties;
 
diff --git a/rocketmq-spring-boot/src/main/resources/META-INF/spring.factories b/rocketmq-spring-boot/src/main/resources/META-INF/spring.factories
index 92ff818..d976354 100644
--- a/rocketmq-spring-boot/src/main/resources/META-INF/spring.factories
+++ b/rocketmq-spring-boot/src/main/resources/META-INF/spring.factories
@@ -1,2 +1,2 @@
 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-org.apache.rocketmq.spring.config.RocketMQAutoConfiguration
\ No newline at end of file
+org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration
\ No newline at end of file
diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java
similarity index 99%
rename from rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
rename to rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java
index c719e8c..f78251e 100644
--- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
+++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.rocketmq.spring.config;
+package org.apache.rocketmq.spring.autoconfigure;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.rocketmq.client.producer.DefaultMQProducer;


[rocketmq-spring] 24/37: Update PULL_REQUEST_TEMPLATE.md

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit c12b757e8e184ec5bb4b7e83c3d4bc5ea1ee67b3
Author: von gosling <vo...@apache.org>
AuthorDate: Tue Dec 18 23:35:13 2018 +0800

    Update PULL_REQUEST_TEMPLATE.md
---
 .github/PULL_REQUEST_TEMPLATE.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 143dac8..5799172 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -15,6 +15,6 @@ Follow this checklist to help us incorporate your contribution quickly and easil
 - [x] Make sure there is a [Github issue](https://github.com/apache/rocketmq/issues) filed for the change (usually before you start working on it). Trivial changes like typos do not require a Github issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue. 
 - [x] Format the pull request title like `[ISSUE #123] Fix UnknownException when host config not exist`. Each commit in the pull request should have a meaningful subject line and body.
 - [x] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
-- [x] Write necessary unit-test(over 80% coverage) to verify your logic correction, more mock a little better when cross module dependency exist. If the new feature or significant change is committed, please remember to add integration-test in [test module](https://github.com/apache/rocketmq/tree/master/test).
+- [x] Write necessary unit-test(over 80% coverage) to verify your logic correction, more mock a little better when cross module dependency exist. 
 - [x] Run `mvn -B clean apache-rat:check findbugs:findbugs checkstyle:checkstyle` to make sure basic checks pass. Run `mvn clean install -DskipITs` to make sure unit-test pass. Run `mvn clean test-compile failsafe:integration-test`  to make sure integration-test pass.
 - [ ] If this contribution is large, please file an [Apache Individual Contributor License Agreement](http://www.apache.org/licenses/#clas).


[rocketmq-spring] 22/37: Rationalise use of ObjectMapper

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit ef3649f9a5266d4af5da5ff9297d85ef874342f1
Author: Stephane Nicoll <sn...@pivotal.io>
AuthorDate: Fri Dec 14 11:12:49 2018 +0100

    Rationalise use of ObjectMapper
    
    This commit makes sure that an ObjectMapper is created only if the
    regular Spring Boot auto-configuration didn't get a chance to create
    one.
    
    In more complex scenario where multiple ObjectMapper instances are
    available in the context, a user has to provide an ObjectMapper named
    `rocketMQMessageObjectMapper`.
---
 .../config/JacksonFallbackConfiguration.java       | 34 +++++++++++++++
 .../config/ListenerContainerConfiguration.java     |  6 +--
 .../spring/config/RocketMQAutoConfiguration.java   | 34 ++++-----------
 .../config/RocketMQAutoConfigurationTest.java      | 48 ++++++++++++++++++++++
 4 files changed, 92 insertions(+), 30 deletions(-)

diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/JacksonFallbackConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/JacksonFallbackConfiguration.java
new file mode 100644
index 0000000..a66887a
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/JacksonFallbackConfiguration.java
@@ -0,0 +1,34 @@
+/*
+ * 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.rocketmq.spring.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnMissingBean(ObjectMapper.class)
+class JacksonFallbackConfiguration {
+
+    @Bean
+    public ObjectMapper rocketMQMessageObjectMapper() {
+        return new ObjectMapper();
+    }
+
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
index 9f78a19..625bae6 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
@@ -28,7 +28,6 @@ import org.slf4j.LoggerFactory;
 import org.springframework.aop.support.AopUtils;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.SmartInitializingSingleton;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.support.BeanDefinitionValidationException;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
@@ -56,11 +55,10 @@ public class ListenerContainerConfiguration implements ApplicationContextAware,
 
     private ObjectMapper objectMapper;
 
-    public ListenerContainerConfiguration(
-        @Qualifier("rocketMQMessageObjectMapper") ObjectMapper objectMapper,
+    public ListenerContainerConfiguration(ObjectMapper rocketMQMessageObjectMapper,
         StandardEnvironment environment,
         RocketMQProperties rocketMQProperties) {
-        this.objectMapper = objectMapper;
+        this.objectMapper = rocketMQMessageObjectMapper;
         this.environment = environment;
         this.rocketMQProperties = rocketMQProperties;
     }
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
index b65dee1..a2efeb6 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
@@ -18,15 +18,16 @@
 package org.apache.rocketmq.spring.config;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.rocketmq.client.MQAdmin;
 import org.apache.rocketmq.client.producer.DefaultMQProducer;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -34,12 +35,12 @@ import org.springframework.context.annotation.Import;
 import org.springframework.context.annotation.Role;
 import org.springframework.util.Assert;
 
-import java.util.Objects;
-
 @Configuration
 @EnableConfigurationProperties(RocketMQProperties.class)
+@ConditionalOnClass({ MQAdmin.class, ObjectMapper.class })
 @ConditionalOnProperty(prefix = "spring.rocketmq", value = "name-server")
-@Import(ListenerContainerConfiguration.class)
+@Import({ JacksonFallbackConfiguration.class, ListenerContainerConfiguration.class })
+@AutoConfigureAfter(JacksonAutoConfiguration.class)
 public class RocketMQAutoConfiguration {
 
     @Bean
@@ -67,17 +68,10 @@ public class RocketMQAutoConfiguration {
     @Bean(destroyMethod = "destroy")
     @ConditionalOnBean(DefaultMQProducer.class)
     @ConditionalOnMissingBean(RocketMQTemplate.class)
-    public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer,
-        @Autowired(required = false)
-        @Qualifier("rocketMQMessageObjectMapper")
-            ObjectMapper objectMapper) {
+    public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, ObjectMapper rocketMQMessageObjectMapper) {
         RocketMQTemplate rocketMQTemplate = new RocketMQTemplate();
         rocketMQTemplate.setProducer(mqProducer);
-        if (Objects.nonNull(objectMapper)) {
-            rocketMQTemplate.setObjectMapper(objectMapper);
-        } else {
-            throw new IllegalStateException("Can not inject null objectMapper into RocketMQTemplate!");
-        }
+        rocketMQTemplate.setObjectMapper(rocketMQMessageObjectMapper);
         return rocketMQTemplate;
     }
 
@@ -96,16 +90,4 @@ public class RocketMQAutoConfiguration {
         return new RocketMQTransactionAnnotationProcessor(transactionHandlerRegistry);
     }
 
-    @Configuration
-    @ConditionalOnClass(ObjectMapper.class)
-    static class JacksonConfiguration {
-
-        @Bean
-        @ConditionalOnMissingBean(ObjectMapper.class)
-        public ObjectMapper rocketMQMessageObjectMapper() {
-            return new ObjectMapper();
-        }
-
-    }
-
 }
diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
index c0fa370..b819e3f 100644
--- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
+++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.rocketmq.spring.config;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.rocketmq.client.producer.DefaultMQProducer;
 import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
 import org.apache.rocketmq.spring.core.RocketMQListener;
@@ -81,6 +82,28 @@ public class RocketMQAutoConfigurationTest {
 
     }
 
+    @Test
+    public void testRocketMQListenerWithCustomObjectMapper() {
+        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876").
+                withUserConfiguration(TestConfig.class, CustomObjectMapperConfig.class).
+                run((context) -> {
+                    assertThat(context).hasSingleBean(DefaultRocketMQListenerContainer.class);
+                    assertThat(context.getBean(DefaultRocketMQListenerContainer.class).getObjectMapper())
+                            .isSameAs(context.getBean(CustomObjectMapperConfig.class).testObjectMapper());
+                });
+    }
+
+    @Test
+    public void testRocketMQListenerWithSeveralObjectMappers() {
+        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876").
+                withUserConfiguration(TestConfig.class, CustomObjectMappersConfig.class).
+                run((context) -> {
+                    assertThat(context).hasSingleBean(DefaultRocketMQListenerContainer.class);
+                    assertThat(context.getBean(DefaultRocketMQListenerContainer.class).getObjectMapper())
+                            .isSameAs(context.getBean(CustomObjectMappersConfig.class).rocketMQMessageObjectMapper());
+                });
+    }
+
     @Configuration
     static class TestConfig {
 
@@ -90,6 +113,31 @@ public class RocketMQAutoConfigurationTest {
         }
     }
 
+    @Configuration
+    static class CustomObjectMapperConfig {
+
+        @Bean
+        public ObjectMapper testObjectMapper() {
+            return new ObjectMapper();
+        }
+
+    }
+
+    @Configuration
+    static class CustomObjectMappersConfig {
+
+        @Bean
+        public ObjectMapper testObjectMapper() {
+            return new ObjectMapper();
+        }
+
+        @Bean
+        public ObjectMapper rocketMQMessageObjectMapper() {
+            return new ObjectMapper();
+        }
+
+    }
+
     @RocketMQMessageListener(consumerGroup = "abc", topic = "test")
     static class MyMessageListener implements RocketMQListener {
 


[rocketmq-spring] 06/37: Update README.md

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit e44f1737f4851326f863d79731351466cffe3132
Author: von gosling <vo...@apache.org>
AuthorDate: Thu Dec 6 17:36:09 2018 +0800

    Update README.md
---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index c84b3e9..50c0b3b 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
 
 ## Introduction
 
-Thi project aims to help developers quickly integrate [RocketMQ](http://rocketmq.apache.org/) in [Spring Boot](http://projects.spring.io/spring-boot/). Support the Spring Message specification to facilitate developers to quickly switch from other MQ to RocketMQ.
+This project aims to help developers quickly integrate [RocketMQ](http://rocketmq.apache.org/) with [Spring Boot](http://projects.spring.io/spring-boot/). 
 
 ## How To Contribute
 


[rocketmq-spring] 10/37: Update README_zh_CN.md

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 805d62b40c87cc4ea1775b81ee665dfb0f16123b
Author: von gosling <vo...@apache.org>
AuthorDate: Fri Dec 7 12:36:46 2018 +0800

    Update README_zh_CN.md
---
 README_zh_CN.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README_zh_CN.md b/README_zh_CN.md
index c7c928a..168230d 100644
--- a/README_zh_CN.md
+++ b/README_zh_CN.md
@@ -1,4 +1,4 @@
-# rocketmq-spring-boot
+# RocketMQ-Spring
 
 [English](./README.md)
 


[rocketmq-spring] 29/37: Merge branch 'master' into master

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit d0f973f41b779f5d045f97e4629b82aa88b4fa39
Merge: 9db9c38 07598bf
Author: von gosling <vo...@apache.org>
AuthorDate: Wed Dec 19 15:37:54 2018 +0800

    Merge branch 'master' into master

 .../config/JacksonFallbackConfiguration.java       | 34 +++++++++++++++
 .../config/ListenerContainerConfiguration.java     |  6 +--
 .../spring/config/RocketMQAutoConfiguration.java   | 34 ++++-----------
 .../config/RocketMQAutoConfigurationTest.java      | 48 ++++++++++++++++++++++
 4 files changed, 92 insertions(+), 30 deletions(-)

diff --cc rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
index 10dfb5e,a2efeb6..c031335
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
@@@ -34,12 -35,12 +35,12 @@@ import org.springframework.context.anno
  import org.springframework.context.annotation.Role;
  import org.springframework.util.Assert;
  
- import java.util.Objects;
- 
  @Configuration
  @EnableConfigurationProperties(RocketMQProperties.class)
+ @ConditionalOnClass({ MQAdmin.class, ObjectMapper.class })
 -@ConditionalOnProperty(prefix = "spring.rocketmq", value = "name-server")
 +@ConditionalOnProperty(prefix = "rocketmq", value = "name-server")
- @Import(ListenerContainerConfiguration.class)
+ @Import({ JacksonFallbackConfiguration.class, ListenerContainerConfiguration.class })
+ @AutoConfigureAfter(JacksonAutoConfiguration.class)
  public class RocketMQAutoConfiguration {
  
      @Bean


[rocketmq-spring] 35/37: Change project version to 2.0.1-SNAPSHOT

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 8e1466e75f77998ddbfd7e1571f75ad55eca4cc3
Author: Heng Du <du...@gmail.com>
AuthorDate: Mon Dec 24 11:41:04 2018 +0800

    Change project version to 2.0.1-SNAPSHOT
---
 rocketmq-spring-boot-parent/pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml
index b5a3dbc..b151179 100644
--- a/rocketmq-spring-boot-parent/pom.xml
+++ b/rocketmq-spring-boot-parent/pom.xml
@@ -39,7 +39,7 @@
         <spring.boot.version>2.0.5.RELEASE</spring.boot.version>
         <spring.version>5.1.0.RELEASE</spring.version>
 
-        <rocketmq.spring.boot.version>${project.version}</rocketmq.spring.boot.version>
+        <rocketmq.spring.boot.version>2.0.1-SNAPSHOT</rocketmq.spring.boot.version>
 
         <rocketmq-version>4.3.2</rocketmq-version>
         <slf4j.version>1.7.25</slf4j.version>


[rocketmq-spring] 19/37: Fixed this issure https://github.com/apache/rocketmq-spring/issues/10

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 13138560b2d991ec16ebd28a2720025d6903e70a
Author: odbozhou <87...@qq.com>
AuthorDate: Sat Dec 15 11:59:39 2018 +0800

    Fixed this issure https://github.com/apache/rocketmq-spring/issues/10
---
 .../support/DefaultRocketMQListenerContainer.java  |  8 ++-
 .../DefaultRocketMQListenerContainerTest.java      | 61 ++++++++++++++++++++++
 2 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java
index 1993035..ce1b388 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java
@@ -348,7 +348,13 @@ public class DefaultRocketMQListenerContainer implements InitializingBean, Rocke
     }
 
     private Class getMessageType() {
-        Type[] interfaces = AopUtils.getTargetClass(rocketMQListener).getGenericInterfaces();
+        Class<?> targetClass = AopUtils.getTargetClass(rocketMQListener);
+        Type[] interfaces = targetClass.getGenericInterfaces();
+        Class<?> superclass = targetClass.getSuperclass();
+        while ((Objects.isNull(interfaces) || 0 == interfaces.length) && Objects.nonNull(superclass)) {
+            interfaces = superclass.getGenericInterfaces();
+            superclass = targetClass.getSuperclass();
+        }
         if (Objects.nonNull(interfaces)) {
             for (Type type : interfaces) {
                 if (type instanceof ParameterizedType) {
diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainerTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainerTest.java
new file mode 100644
index 0000000..5787689
--- /dev/null
+++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainerTest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.spring.support;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.junit.Test;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import static org.assertj.core.api.Assertions.assertThat;
+public class DefaultRocketMQListenerContainerTest {
+    @Test
+    public void testGetMessageType() throws NoSuchMethodException {
+        DefaultRocketMQListenerContainer listenerContainer = new DefaultRocketMQListenerContainer();
+        Method getMessageType = DefaultRocketMQListenerContainer.class.getDeclaredMethod("getMessageType");
+        getMessageType.setAccessible(true);
+        try {
+            listenerContainer.setRocketMQListener(new BaseStringConsumer());
+            Class result = (Class) getMessageType.invoke(listenerContainer);
+            assertThat(result.getName().equals(String.class.getName())).isTrue();
+            listenerContainer.setRocketMQListener(new BaseMessageExtConsumer());
+            result = (Class) getMessageType.invoke(listenerContainer);
+            assertThat(result.getName().equals(MessageExt.class.getName())).isTrue();
+            listenerContainer.setRocketMQListener(new ConcreteStringConsumer());
+            result = (Class) getMessageType.invoke(listenerContainer);
+            assertThat(result.getName().equals(String.class.getName())).isTrue();
+            listenerContainer.setRocketMQListener(new ConcreteMessageExtConsumer());
+            result = (Class) getMessageType.invoke(listenerContainer);
+            assertThat(result.getName().equals(MessageExt.class.getName())).isTrue();
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            e.printStackTrace();
+        }
+    }
+}
+class BaseStringConsumer implements RocketMQListener<String> {
+    @Override
+    public void onMessage(String message) {
+    }
+}
+class ConcreteStringConsumer extends BaseStringConsumer {
+}
+class BaseMessageExtConsumer implements RocketMQListener<MessageExt> {
+    @Override
+    public void onMessage(MessageExt message) {
+    }
+}
+class ConcreteMessageExtConsumer extends BaseMessageExtConsumer {
+}
\ No newline at end of file


[rocketmq-spring] 11/37: Support configuration property with relaxed names

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 11b9a50a6580e8d5f3259909d724dacbd67ec47d
Author: walking98 <wi...@gmail.com>
AuthorDate: Wed Dec 12 11:05:41 2018 +0800

    Support configuration property with relaxed names
---
 .../src/main/resources/application.properties            |  2 +-
 .../spring/config/RocketMQAutoConfiguration.java         |  9 +++++----
 .../spring/config/RocketMQAutoConfigurationTest.java     | 16 +++++++++++++---
 3 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties
index 2187442..f14b1ba 100644
--- a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties
+++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties
@@ -1,4 +1,4 @@
-spring.rocketmq.nameServer=localhost:9876
+spring.rocketmq.name-server=localhost:9876
 spring.rocketmq.producer.group=my-group1
 spring.rocketmq.topic=string-topic
 spring.rocketmq.orderTopic=order-paid-topic
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
index d229d2b..e62eb8d 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
@@ -38,18 +38,18 @@ import java.util.Objects;
 
 @Configuration
 @EnableConfigurationProperties(RocketMQProperties.class)
-@ConditionalOnProperty(prefix = "spring.rocketmq", value = "nameServer")
+@ConditionalOnProperty(prefix = "spring.rocketmq", value = "name-server")
 @Import(ListenerContainerConfiguration.class)
 public class RocketMQAutoConfiguration {
 
     @Bean
     @ConditionalOnMissingBean(DefaultMQProducer.class)
-    @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"nameServer", "producer.group"})
+    @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"name-server", "producer.group"})
     public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties) {
         RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer();
         String nameServer = rocketMQProperties.getNameServer();
         String groupName = producerConfig.getGroup();
-        Assert.hasText(nameServer, "[spring.rocketmq.nameServer] must not be null");
+        Assert.hasText(nameServer, "[spring.rocketmq.name-server] must not be null");
         Assert.hasText(groupName, "[spring.rocketmq.producer.group] must not be null");
 
         DefaultMQProducer producer = new DefaultMQProducer(groupName);
@@ -98,7 +98,8 @@ public class RocketMQAutoConfiguration {
     @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME)
     @ConditionalOnBean(TransactionHandlerRegistry.class)
     @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-    public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor(TransactionHandlerRegistry transactionHandlerRegistry) {
+    public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor(
+        TransactionHandlerRegistry transactionHandlerRegistry) {
         return new RocketMQTransactionAnnotationProcessor(transactionHandlerRegistry);
     }
 }
diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
index a841a74..2656249 100644
--- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
+++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
@@ -48,8 +48,8 @@ public class RocketMQAutoConfigurationTest {
 
 
     @Test
-    public void testDefaultMQProducer() {
-        runner.withPropertyValues("spring.rocketmq.nameServer=127.0.0.1:9876",
+    public void testDefaultMQProducerWithRelaxPropertyName() {
+        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876",
                 "spring.rocketmq.producer.group=spring_rocketmq").
                 run((context) -> {
                     assertThat(context).hasSingleBean(DefaultMQProducer.class);
@@ -59,8 +59,18 @@ public class RocketMQAutoConfigurationTest {
     }
 
     @Test
+    public void testDefaultMQProducer() {
+        runner.withPropertyValues("spring.rocketmq.nameServer=127.0.0.1:9876",
+            "spring.rocketmq.producer.group=spring_rocketmq").
+            run((context) -> {
+                assertThat(context).hasSingleBean(DefaultMQProducer.class);
+            });
+
+    }
+
+    @Test
     public void testRocketMQListenerContainer() {
-        runner.withPropertyValues("spring.rocketmq.nameServer=127.0.0.1:9876").
+        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876").
             withUserConfiguration(TestConfig.class).
             run((context) -> {
                 // No producer on consume side


[rocketmq-spring] 36/37: Merge pull request #20 from snicoll/auto-configure-split

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 5b75cbc4ae527358dc087dedc18f0e055d339d1d
Merge: 8e1466e 34388b8
Author: von gosling <vo...@apache.org>
AuthorDate: Mon Dec 24 14:27:17 2018 +0800

    Merge pull request #20 from snicoll/auto-configure-split
    
    Separate auto-configuration in a dedicated package

 .../{config => autoconfigure}/JacksonFallbackConfiguration.java      | 2 +-
 .../{config => autoconfigure}/ListenerContainerConfiguration.java    | 4 ++--
 .../spring/{config => autoconfigure}/RocketMQAutoConfiguration.java  | 5 ++++-
 .../spring/{config => autoconfigure}/RocketMQProperties.java         | 2 +-
 rocketmq-spring-boot/src/main/resources/META-INF/spring.factories    | 2 +-
 .../{config => autoconfigure}/RocketMQAutoConfigurationTest.java     | 2 +-
 6 files changed, 10 insertions(+), 7 deletions(-)


[rocketmq-spring] 37/37: Revert RocketMQ Spring Version

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit c21077cb33a4603cd9de0b2a0cd3fe01d26195aa
Author: ShannonDing <li...@163.com>
AuthorDate: Thu Jan 17 21:19:36 2019 +0800

    Revert RocketMQ Spring Version
---
 pom.xml                              | 5 ++---
 rocketmq-spring-boot-parent/pom.xml  | 7 +++----
 rocketmq-spring-boot-starter/pom.xml | 5 ++---
 rocketmq-spring-boot/pom.xml         | 5 ++---
 4 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/pom.xml b/pom.xml
index 09ebeec..3594811 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,13 +16,12 @@
   ~ 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">
     <modelVersion>4.0.0</modelVersion>
 
     <groupId>org.apache.rocketmq</groupId>
     <artifactId>rocketmq-spring-boot-build</artifactId>
-    <version>2.0.1-SNAPSHOT</version>
+    <version>2.0.2-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>RocketMQ Spring Boot Build</name>
diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml
index b151179..a0af0cf 100644
--- a/rocketmq-spring-boot-parent/pom.xml
+++ b/rocketmq-spring-boot-parent/pom.xml
@@ -16,14 +16,13 @@
   ~ 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">
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
         <groupId>org.apache.rocketmq</groupId>
         <artifactId>rocketmq-spring-boot-build</artifactId>
-        <version>2.0.1-SNAPSHOT</version>
+        <version>2.0.2-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
@@ -39,7 +38,7 @@
         <spring.boot.version>2.0.5.RELEASE</spring.boot.version>
         <spring.version>5.1.0.RELEASE</spring.version>
 
-        <rocketmq.spring.boot.version>2.0.1-SNAPSHOT</rocketmq.spring.boot.version>
+        <rocketmq.spring.boot.version>2.0.2-SNAPSHOT</rocketmq.spring.boot.version>
 
         <rocketmq-version>4.3.2</rocketmq-version>
         <slf4j.version>1.7.25</slf4j.version>
diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml
index 763fce6..bdedcc5 100644
--- a/rocketmq-spring-boot-starter/pom.xml
+++ b/rocketmq-spring-boot-starter/pom.xml
@@ -16,14 +16,13 @@
   ~ 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">
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
         <groupId>org.apache.rocketmq</groupId>
         <artifactId>rocketmq-spring-boot-parent</artifactId>
-        <version>2.0.1-SNAPSHOT</version>
+        <version>2.0.2-SNAPSHOT</version>
         <relativePath>../rocketmq-spring-boot-parent/pom.xml</relativePath>
     </parent>
 
diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml
index 85dedd1..30d137b 100644
--- a/rocketmq-spring-boot/pom.xml
+++ b/rocketmq-spring-boot/pom.xml
@@ -16,14 +16,13 @@
   ~ 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">
     <modelVersion>4.0.0</modelVersion>
 
     <parent>
         <groupId>org.apache.rocketmq</groupId>
         <artifactId>rocketmq-spring-boot-parent</artifactId>
-        <version>2.0.1-SNAPSHOT</version>
+        <version>2.0.2-SNAPSHOT</version>
         <relativePath>../rocketmq-spring-boot-parent/pom.xml</relativePath>
     </parent>
 


[rocketmq-spring] 12/37: Modify to appropriate property name

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 141ddbb0cf93c88ef15b73a684b2f8959356c822
Author: walking98 <wi...@gmail.com>
AuthorDate: Wed Dec 12 11:30:27 2018 +0800

    Modify to appropriate property name
---
 .../rocketmq/spring/config/RocketMQAutoConfiguration.java      |  2 +-
 .../org/apache/rocketmq/spring/config/RocketMQProperties.java  | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
index e62eb8d..bd7cda1 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
@@ -58,7 +58,7 @@ public class RocketMQAutoConfiguration {
         producer.setRetryTimesWhenSendFailed(producerConfig.getRetryTimesWhenSendFailed());
         producer.setRetryTimesWhenSendAsyncFailed(producerConfig.getRetryTimesWhenSendAsyncFailed());
         producer.setMaxMessageSize(producerConfig.getMaxMessageSize());
-        producer.setCompressMsgBodyOverHowmuch(producerConfig.getCompressMessageBodyOverHowmuch());
+        producer.setCompressMsgBodyOverHowmuch(producerConfig.getCompressMessageBodyThreshold());
         producer.setRetryAnotherBrokerWhenNotStoreOK(producerConfig.isRetryAnotherBrokerWhenNotStoreOk());
 
         return producer;
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
index 8590e05..07e9e06 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
@@ -61,7 +61,7 @@ public class RocketMQProperties {
         /**
          * Compress message body threshold, namely, message body larger than 4k will be compressed on default.
          */
-        private int compressMessageBodyOverHowmuch = 1024 * 4;
+        private int compressMessageBodyThreshold = 1024 * 4;
 
         /**
          * Maximum number of retry to perform internally before claiming sending failure in synchronous mode.
@@ -101,12 +101,12 @@ public class RocketMQProperties {
             this.sendMessageTimeout = sendMessageTimeout;
         }
 
-        public int getCompressMessageBodyOverHowmuch() {
-            return compressMessageBodyOverHowmuch;
+        public int getCompressMessageBodyThreshold() {
+            return compressMessageBodyThreshold;
         }
 
-        public void setCompressMessageBodyOverHowmuch(int compressMessageBodyOverHowmuch) {
-            this.compressMessageBodyOverHowmuch = compressMessageBodyOverHowmuch;
+        public void setCompressMessageBodyThreshold(int compressMessageBodyThreshold) {
+            this.compressMessageBodyThreshold = compressMessageBodyThreshold;
         }
 
         public int getRetryTimesWhenSendFailed() {


[rocketmq-spring] 07/37: RocketMQTransactionAnnotationProcessor @Bean factory method must be declared static

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit cd95b345ec67c13713d968dda5fa80474ec02d8c
Author: vongosling <vo...@apache.org>
AuthorDate: Fri Dec 7 11:40:19 2018 +0800

    RocketMQTransactionAnnotationProcessor @Bean factory method must be declared static
---
 .../org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
index c22c6ee..d229d2b 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
@@ -98,7 +98,7 @@ public class RocketMQAutoConfiguration {
     @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME)
     @ConditionalOnBean(TransactionHandlerRegistry.class)
     @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-    public RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor(TransactionHandlerRegistry transactionHandlerRegistry) {
+    public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor(TransactionHandlerRegistry transactionHandlerRegistry) {
         return new RocketMQTransactionAnnotationProcessor(transactionHandlerRegistry);
     }
 }


[rocketmq-spring] 09/37: Update README.md

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 0c7fed8fc8d4c0588186b7143a385483ec152319
Author: von gosling <vo...@apache.org>
AuthorDate: Fri Dec 7 12:36:15 2018 +0800

    Update README.md
---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 37e9f83..89ac93e 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Rocketmq-Spring
+# RocketMQ-Spring
 
 [中文](./README_zh_CN.md)
 


[rocketmq-spring] 20/37: Merge pull request #11 from odbozhou/master

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit d7fbcbf9a3f69a3f33eb30bfd1de2e1a3c249d87
Merge: 3ba290d 1313856
Author: von gosling <vo...@apache.org>
AuthorDate: Mon Dec 17 13:54:48 2018 +0800

    Merge pull request #11 from odbozhou/master
    
    Enhance consumer classes so that consumer classes can be inherited

 .../support/DefaultRocketMQListenerContainer.java  |  8 ++-
 .../DefaultRocketMQListenerContainerTest.java      | 61 ++++++++++++++++++++++
 2 files changed, 68 insertions(+), 1 deletion(-)


[rocketmq-spring] 18/37: Merge pull request #2 from walking98/master

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 3ba290d479ae4bc2c0cb41d2b0629caab4c90ad0
Merge: e895eec 06dfd51
Author: von gosling <vo...@apache.org>
AuthorDate: Fri Dec 14 16:24:04 2018 +0800

    Merge pull request #2 from walking98/master
    
    Support configuration property with relaxed names

 README.md                                              | 18 +++++++++---------
 README_zh_CN.md                                        | 18 +++++++++---------
 pom.xml                                                |  2 +-
 rocketmq-spring-boot-parent/pom.xml                    |  4 ++--
 rocketmq-spring-boot-samples/pom.xml                   |  2 +-
 .../src/main/resources/application.properties          |  2 +-
 rocketmq-spring-boot-starter/pom.xml                   |  2 +-
 rocketmq-spring-boot/pom.xml                           |  2 +-
 .../spring/config/RocketMQAutoConfiguration.java       |  5 +++--
 .../rocketmq/spring/config/RocketMQProperties.java     | 10 +++++-----
 .../spring/config/RocketMQAutoConfigurationTest.java   | 14 ++++++++++++--
 11 files changed, 45 insertions(+), 34 deletions(-)


[rocketmq-spring] 32/37: Merge pull request #18 from walking98/master

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit d3b876567ae14bed0d982380f38fd810a848e072
Merge: 85b9e2a 0abbd0b
Author: von gosling <vo...@apache.org>
AuthorDate: Wed Dec 19 16:18:12 2018 +0800

    Merge pull request #18 from walking98/master
    
    Adjust config property name RetryAnotherBrokerWhenNotStoreOK  -> retr…

 README.md                                                      |  4 ++--
 README_zh_CN.md                                                |  4 ++--
 .../rocketmq/spring/config/RocketMQAutoConfiguration.java      |  2 +-
 .../org/apache/rocketmq/spring/config/RocketMQProperties.java  | 10 +++++-----
 .../rocketmq/spring/config/RocketMQAutoConfigurationTest.java  |  4 ++--
 5 files changed, 12 insertions(+), 12 deletions(-)


[rocketmq-spring] 33/37: Add maven release plugin

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 540ce6605e42414737a57e3ca0ad7163ca577a92
Author: duhenglucky <du...@gmail.com>
AuthorDate: Fri Dec 21 12:09:33 2018 +0800

    Add maven release plugin
---
 pom.xml | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/pom.xml b/pom.xml
index ba39a3e..09ebeec 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,6 +29,36 @@
     <description>Build for Apache RocketMQ Spring Boot Support</description>
     <url>https://github.com/apache/rocketmq-spring</url>
 
+
+    <scm>
+        <url>git@github.com:apache/rocketmq-spring.git</url>
+        <connection>scm:git:git@github.com:apache/rocketmq-spring.git</connection>
+        <developerConnection>scm:git:git@github.com:apache/rocketmq-spring.git</developerConnection>
+        <tag>HEAD</tag>
+    </scm>
+
+    <mailingLists>
+        <mailingList>
+            <name>Development List</name>
+            <subscribe>dev-subscribe@rocketmq.apache.org</subscribe>
+            <unsubscribe>dev-unsubscribe@rocketmq.apache.org</unsubscribe>
+            <post>dev@rocketmq.apache.org</post>
+        </mailingList>
+        <mailingList>
+            <name>User List</name>
+            <subscribe>users-subscribe@rocketmq.apache.org</subscribe>
+            <unsubscribe>users-unsubscribe@rocketmq.apache.org</unsubscribe>
+            <post>users@rocketmq.apache.org</post>
+        </mailingList>
+        <mailingList>
+            <name>Commits List</name>
+            <subscribe>commits-subscribe@rocketmq.apache.org</subscribe>
+            <unsubscribe>commits-unsubscribe@rocketmq.apache.org</unsubscribe>
+            <post>commits@rocketmq.apache.org</post>
+        </mailingList>
+    </mailingLists>
+
+
     <organization>
         <name>Apache Software Foundation</name>
         <url>http://www.apache.org</url>


[rocketmq-spring] 17/37: Make version as 2.0.1-SNAPSHOT

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 06dfd51d90253b78d8f704f3d3c0e5fd31e3e763
Author: walking98 <wi...@gmail.com>
AuthorDate: Fri Dec 14 16:19:03 2018 +0800

    Make version as 2.0.1-SNAPSHOT
---
 README.md                            | 2 +-
 README_zh_CN.md                      | 2 +-
 pom.xml                              | 2 +-
 rocketmq-spring-boot-parent/pom.xml  | 2 +-
 rocketmq-spring-boot-samples/pom.xml | 2 +-
 rocketmq-spring-boot-starter/pom.xml | 2 +-
 rocketmq-spring-boot/pom.xml         | 2 +-
 7 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md
index fa5beeb..fc4689e 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ We are always very happy to have contributions, whether for trivial cleanups or
 
 Please see the complete sample [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples)
 
-Note: Current RELEASE.VERSION=2.0.0-SNAPSHOT
+Note: Current RELEASE.VERSION=2.0.1-SNAPSHOT (public review phase)
 
 ```xml
 <!--add dependency in pom.xml-->
diff --git a/README_zh_CN.md b/README_zh_CN.md
index 6c2a074..8b4d136 100644
--- a/README_zh_CN.md
+++ b/README_zh_CN.md
@@ -30,7 +30,7 @@
 
 下面列出来了一些关键点,完整的示例请参考: [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples)
 
-注意:当前的RELEASE.VERSION=2.0.0-SNAPSHOT
+注意:当前的RELEASE.VERSION=2.0.1-SNAPSHOT 目前在公开review阶段。
 
 ```xml
 <!--在pom.xml中添加依赖-->
diff --git a/pom.xml b/pom.xml
index 7212b4b..ba39a3e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,7 +22,7 @@
 
     <groupId>org.apache.rocketmq</groupId>
     <artifactId>rocketmq-spring-boot-build</artifactId>
-    <version>2.0.0-SNAPSHOT</version>
+    <version>2.0.1-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>RocketMQ Spring Boot Build</name>
diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml
index cbeea37..b337386 100644
--- a/rocketmq-spring-boot-parent/pom.xml
+++ b/rocketmq-spring-boot-parent/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.apache.rocketmq</groupId>
         <artifactId>rocketmq-spring-boot-build</artifactId>
-        <version>2.0.0-SNAPSHOT</version>
+        <version>2.0.1-SNAPSHOT</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
diff --git a/rocketmq-spring-boot-samples/pom.xml b/rocketmq-spring-boot-samples/pom.xml
index 838268a..c4568fd 100644
--- a/rocketmq-spring-boot-samples/pom.xml
+++ b/rocketmq-spring-boot-samples/pom.xml
@@ -36,7 +36,7 @@
     </modules>
 
     <properties>
-        <rocketmq-spring-boot-starter-version>2.0.0-SNAPSHOT</rocketmq-spring-boot-starter-version>
+        <rocketmq-spring-boot-starter-version>2.0.1-SNAPSHOT</rocketmq-spring-boot-starter-version>
     </properties>
 
     <dependencies>
diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml
index ff9d16a..763fce6 100644
--- a/rocketmq-spring-boot-starter/pom.xml
+++ b/rocketmq-spring-boot-starter/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.apache.rocketmq</groupId>
         <artifactId>rocketmq-spring-boot-parent</artifactId>
-        <version>2.0.0-SNAPSHOT</version>
+        <version>2.0.1-SNAPSHOT</version>
         <relativePath>../rocketmq-spring-boot-parent/pom.xml</relativePath>
     </parent>
 
diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml
index 67f0f4c..3cf574d 100644
--- a/rocketmq-spring-boot/pom.xml
+++ b/rocketmq-spring-boot/pom.xml
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.apache.rocketmq</groupId>
         <artifactId>rocketmq-spring-boot-parent</artifactId>
-        <version>2.0.0-SNAPSHOT</version>
+        <version>2.0.1-SNAPSHOT</version>
         <relativePath>../rocketmq-spring-boot-parent/pom.xml</relativePath>
     </parent>
 


[rocketmq-spring] 14/37: Polish

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 95e3f5c66a38b941bde6b020c55c31e81a91f2c5
Author: Stephane Nicoll <sn...@pivotal.io>
AuthorDate: Wed Dec 12 16:52:15 2018 +0100

    Polish
---
 .../rocketmq/spring/annotation/MessageModel.java   |  2 +-
 .../config/ListenerContainerConfiguration.java     |  7 ++----
 .../spring/config/RocketMQAutoConfiguration.java   | 26 +++++++++++++---------
 .../config/RocketMQAutoConfigurationTest.java      |  4 ++--
 4 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/MessageModel.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/MessageModel.java
index 9bdaa64..7de2187 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/MessageModel.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/MessageModel.java
@@ -21,7 +21,7 @@ public enum MessageModel {
     BROADCASTING("BROADCASTING"),
     CLUSTERING("CLUSTERING");
 
-    private String modeCN;
+    private final String modeCN;
 
     MessageModel(String modeCN) {
         this.modeCN = modeCN;
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
index e1fab88..9f78a19 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
@@ -28,12 +28,12 @@ import org.slf4j.LoggerFactory;
 import org.springframework.aop.support.AopUtils;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.SmartInitializingSingleton;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.beans.factory.support.BeanDefinitionValidationException;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Configuration;
 import org.springframework.context.support.GenericApplicationContext;
 import org.springframework.core.env.StandardEnvironment;
 
@@ -42,6 +42,7 @@ import java.util.Objects;
 import java.util.concurrent.atomic.AtomicLong;
 
 
+@Configuration
 public class ListenerContainerConfiguration implements ApplicationContextAware, SmartInitializingSingleton {
     private final static Logger log = LoggerFactory.getLogger(RocketMQAutoConfiguration.class);
 
@@ -55,10 +56,6 @@ public class ListenerContainerConfiguration implements ApplicationContextAware,
 
     private ObjectMapper objectMapper;
 
-    public ListenerContainerConfiguration() {
-    }
-
-    @Autowired
     public ListenerContainerConfiguration(
         @Qualifier("rocketMQMessageObjectMapper") ObjectMapper objectMapper,
         StandardEnvironment environment,
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
index d229d2b..5eb97a5 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
@@ -38,18 +38,18 @@ import java.util.Objects;
 
 @Configuration
 @EnableConfigurationProperties(RocketMQProperties.class)
-@ConditionalOnProperty(prefix = "spring.rocketmq", value = "nameServer")
+@ConditionalOnProperty(prefix = "spring.rocketmq", value = "name-server")
 @Import(ListenerContainerConfiguration.class)
 public class RocketMQAutoConfiguration {
 
     @Bean
     @ConditionalOnMissingBean(DefaultMQProducer.class)
-    @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"nameServer", "producer.group"})
+    @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"name-server", "producer.group"})
     public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties) {
         RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer();
         String nameServer = rocketMQProperties.getNameServer();
         String groupName = producerConfig.getGroup();
-        Assert.hasText(nameServer, "[spring.rocketmq.nameServer] must not be null");
+        Assert.hasText(nameServer, "[spring.rocketmq.name-server] must not be null");
         Assert.hasText(groupName, "[spring.rocketmq.producer.group] must not be null");
 
         DefaultMQProducer producer = new DefaultMQProducer(groupName);
@@ -64,13 +64,6 @@ public class RocketMQAutoConfiguration {
         return producer;
     }
 
-    @Bean
-    @ConditionalOnClass(name = "com.fasterxml.jackson.databind.ObjectMapper")
-    @ConditionalOnMissingBean(ObjectMapper.class)
-    public ObjectMapper rocketMQMessageObjectMapper() {
-        return new ObjectMapper();
-    }
-
     @Bean(destroyMethod = "destroy")
     @ConditionalOnBean(DefaultMQProducer.class)
     @ConditionalOnMissingBean(RocketMQTemplate.class)
@@ -101,4 +94,17 @@ public class RocketMQAutoConfiguration {
     public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor(TransactionHandlerRegistry transactionHandlerRegistry) {
         return new RocketMQTransactionAnnotationProcessor(transactionHandlerRegistry);
     }
+
+    @Configuration
+    @ConditionalOnClass(ObjectMapper.class)
+    static class JacksonConfiguration {
+
+        @Bean
+        @ConditionalOnMissingBean(ObjectMapper.class)
+        public ObjectMapper rocketMQMessageObjectMapper() {
+            return new ObjectMapper();
+        }
+
+    }
+
 }
diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
index a841a74..fd4056f 100644
--- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
+++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
@@ -49,7 +49,7 @@ public class RocketMQAutoConfigurationTest {
 
     @Test
     public void testDefaultMQProducer() {
-        runner.withPropertyValues("spring.rocketmq.nameServer=127.0.0.1:9876",
+        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876",
                 "spring.rocketmq.producer.group=spring_rocketmq").
                 run((context) -> {
                     assertThat(context).hasSingleBean(DefaultMQProducer.class);
@@ -60,7 +60,7 @@ public class RocketMQAutoConfigurationTest {
 
     @Test
     public void testRocketMQListenerContainer() {
-        runner.withPropertyValues("spring.rocketmq.nameServer=127.0.0.1:9876").
+        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876").
             withUserConfiguration(TestConfig.class).
             run((context) -> {
                 // No producer on consume side


[rocketmq-spring] 30/37: Merge pull request #14 from walking98/master

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 85b9e2a697a2490eb866cd13b3a424bded8f5579
Merge: 07598bf d0f973f
Author: von gosling <vo...@apache.org>
AuthorDate: Wed Dec 19 15:38:10 2018 +0800

    Merge pull request #14 from walking98/master
    
    Fixed for [ISSUE-9] & [ISSUE-7]

 README.md                                            | 20 ++++++++++----------
 README_zh_CN.md                                      | 20 ++++++++++----------
 .../springboot/consumer/OrderPaidEventConsumer.java  |  2 +-
 .../samples/springboot/consumer/StringConsumer.java  |  2 +-
 .../consumer/StringTransactionalConsumer.java        |  2 +-
 .../src/main/resources/application.properties        | 12 +++++++-----
 .../samples/springboot/ProducerApplication.java      |  8 ++++----
 .../src/main/resources/application.properties        | 14 ++++++++------
 .../config/ListenerContainerConfiguration.java       |  6 ++++--
 .../spring/config/RocketMQAutoConfiguration.java     |  8 ++++----
 .../rocketmq/spring/config/RocketMQProperties.java   |  2 +-
 .../spring/config/TransactionHandlerRegistry.java    |  8 +++++---
 .../rocketmq/spring/core/RocketMQTemplate.java       |  2 ++
 .../support/DefaultRocketMQListenerContainer.java    |  7 ++++++-
 .../spring/config/RocketMQAutoConfigurationTest.java | 10 +++++-----
 15 files changed, 69 insertions(+), 54 deletions(-)


[rocketmq-spring] 15/37: Merge pull request #3 from snicoll/polish-20181212

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit e895eec781dd1196248ab99849f3dea4f6dce13b
Merge: 805d62b 95e3f5c
Author: von gosling <vo...@apache.org>
AuthorDate: Fri Dec 14 11:41:29 2018 +0800

    Merge pull request #3 from snicoll/polish-20181212

 .../rocketmq/spring/annotation/MessageModel.java   |  2 +-
 .../config/ListenerContainerConfiguration.java     |  7 ++----
 .../spring/config/RocketMQAutoConfiguration.java   | 26 +++++++++++++---------
 .../config/RocketMQAutoConfigurationTest.java      |  4 ++--
 4 files changed, 21 insertions(+), 18 deletions(-)


[rocketmq-spring] 28/37: Merge pull request #6 from snicoll/objectmapper-polish

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 07598bf219b42e3331c1b9bfa2b5dff2cf51f01f
Merge: c12b757 ef3649f
Author: von gosling <vo...@apache.org>
AuthorDate: Wed Dec 19 15:22:56 2018 +0800

    Merge pull request #6 from snicoll/objectmapper-polish
    
    Rationalise use of ObjectMapper

 .../config/JacksonFallbackConfiguration.java       | 34 +++++++++++++++
 .../config/ListenerContainerConfiguration.java     |  6 +--
 .../spring/config/RocketMQAutoConfiguration.java   | 34 ++++-----------
 .../config/RocketMQAutoConfigurationTest.java      | 48 ++++++++++++++++++++++
 4 files changed, 92 insertions(+), 30 deletions(-)


[rocketmq-spring] 21/37: Fix the unit-test, format as RocketMQ codestype and fix the logging error when testing

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit c9fd3474d6354d2706f4baf205920c34261cbe01
Author: vongosling <vo...@apache.org>
AuthorDate: Mon Dec 17 15:34:17 2018 +0800

    Fix the unit-test, format as RocketMQ codestype and fix the logging error when testing
---
 rocketmq-spring-boot-parent/pom.xml                |  2 +-
 rocketmq-spring-boot/pom.xml                       | 18 ++------
 .../DefaultRocketMQListenerContainerTest.java      | 53 +++++++++-------------
 3 files changed, 27 insertions(+), 46 deletions(-)

diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml
index b337386..b5a3dbc 100644
--- a/rocketmq-spring-boot-parent/pom.xml
+++ b/rocketmq-spring-boot-parent/pom.xml
@@ -42,7 +42,7 @@
         <rocketmq.spring.boot.version>${project.version}</rocketmq.spring.boot.version>
 
         <rocketmq-version>4.3.2</rocketmq-version>
-        <slf4j.version>1.6.1</slf4j.version>
+        <slf4j.version>1.7.25</slf4j.version>
         <jackson.version>2.9.7</jackson.version>
 
         <java.version>1.8</java.version>
diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml
index 3cf574d..85dedd1 100644
--- a/rocketmq-spring-boot/pom.xml
+++ b/rocketmq-spring-boot/pom.xml
@@ -37,29 +37,29 @@
 
     <dependencies>
         <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot</artifactId>
             <optional>true</optional>
         </dependency>
-
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-autoconfigure</artifactId>
             <optional>true</optional>
         </dependency>
-
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-autoconfigure-processor</artifactId>
             <optional>true</optional>
         </dependency>
-
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
             <scope>test</scope>
         </dependency>
-
         <dependency>
             <groupId>org.apache.rocketmq</groupId>
             <artifactId>rocketmq-client</artifactId>
@@ -70,32 +70,22 @@
                 </exclusion>
             </exclusions>
         </dependency>
-
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-messaging</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-core</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-context</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-aop</artifactId>
         </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainerTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainerTest.java
index 5787689..ea85b98 100644
--- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainerTest.java
+++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainerTest.java
@@ -15,47 +15,38 @@
  * limitations under the License.
  */
 package org.apache.rocketmq.spring.support;
+
 import org.apache.rocketmq.common.message.MessageExt;
 import org.apache.rocketmq.spring.core.RocketMQListener;
 import org.junit.Test;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+
 import static org.assertj.core.api.Assertions.assertThat;
+
 public class DefaultRocketMQListenerContainerTest {
     @Test
-    public void testGetMessageType() throws NoSuchMethodException {
+    public void testGetMessageType() throws Exception {
         DefaultRocketMQListenerContainer listenerContainer = new DefaultRocketMQListenerContainer();
         Method getMessageType = DefaultRocketMQListenerContainer.class.getDeclaredMethod("getMessageType");
         getMessageType.setAccessible(true);
-        try {
-            listenerContainer.setRocketMQListener(new BaseStringConsumer());
-            Class result = (Class) getMessageType.invoke(listenerContainer);
-            assertThat(result.getName().equals(String.class.getName())).isTrue();
-            listenerContainer.setRocketMQListener(new BaseMessageExtConsumer());
-            result = (Class) getMessageType.invoke(listenerContainer);
-            assertThat(result.getName().equals(MessageExt.class.getName())).isTrue();
-            listenerContainer.setRocketMQListener(new ConcreteStringConsumer());
-            result = (Class) getMessageType.invoke(listenerContainer);
-            assertThat(result.getName().equals(String.class.getName())).isTrue();
-            listenerContainer.setRocketMQListener(new ConcreteMessageExtConsumer());
-            result = (Class) getMessageType.invoke(listenerContainer);
-            assertThat(result.getName().equals(MessageExt.class.getName())).isTrue();
-        } catch (IllegalAccessException | InvocationTargetException e) {
-            e.printStackTrace();
-        }
+
+        listenerContainer.setRocketMQListener(new RocketMQListener<String>() {
+            @Override
+            public void onMessage(String message) {
+            }
+        });
+        Class result = (Class)getMessageType.invoke(listenerContainer);
+        assertThat(result.getName().equals(String.class.getName()));
+
+        listenerContainer.setRocketMQListener(new RocketMQListener<MessageExt>() {
+            @Override
+            public void onMessage(MessageExt message) {
+            }
+        });
+        result = (Class)getMessageType.invoke(listenerContainer);
+        assertThat(result.getName().equals(MessageExt.class.getName()));
     }
 }
-class BaseStringConsumer implements RocketMQListener<String> {
-    @Override
-    public void onMessage(String message) {
-    }
-}
-class ConcreteStringConsumer extends BaseStringConsumer {
-}
-class BaseMessageExtConsumer implements RocketMQListener<MessageExt> {
-    @Override
-    public void onMessage(MessageExt message) {
-    }
-}
-class ConcreteMessageExtConsumer extends BaseMessageExtConsumer {
-}
\ No newline at end of file
+
+


[rocketmq-spring] 02/37: First release version 2.0.0

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit d7bc7be61a5b8cb26771f46794ff975da6e257fc
Author: walking98 <wi...@gmail.com>
AuthorDate: Thu Dec 6 17:02:42 2018 +0800

    First release version 2.0.0
---
 .gitignore                                         |  13 +
 LICENSE                                            | 202 +++++++
 NOTICE                                             |   5 +
 README.md                                          | 278 +++++++++-
 README_zh_CN.md                                    | 268 +++++++++
 pom.xml                                            |  80 +++
 rocketmq-spring-boot-parent/pom.xml                | 177 ++++++
 rocketmq-spring-boot-samples/LICENSE               | 202 +++++++
 rocketmq-spring-boot-samples/README.md             |  38 ++
 rocketmq-spring-boot-samples/README_zh_CN.md       |  48 ++
 rocketmq-spring-boot-samples/pom.xml               |  89 +++
 .../rocketmq-consume-demo/pom.xml                  |  31 ++
 .../samples/springboot/ConsumerApplication.java    |  33 ++
 .../samples/springboot/consumer/Checker.java       |  44 ++
 .../springboot/consumer/MessageExtConsumer.java    |  46 ++
 .../consumer/OrderPaidEventConsumer.java           |  36 ++
 .../springboot/consumer/StringConsumer.java        |  34 ++
 .../consumer/StringTransactionalConsumer.java      |  34 ++
 .../samples/springboot/domain/OrderPaidEvent.java  |  54 ++
 .../src/main/resources/application.properties      |   7 +
 .../rocketmq-produce-demo/pom.xml                  |  32 ++
 .../samples/springboot/ProducerApplication.java    | 171 ++++++
 .../samples/springboot/domain/OrderPaidEvent.java  |  50 ++
 .../src/main/resources/application.properties      |   6 +
 .../style/copyright/Apache.xml                     |  23 +
 .../style/copyright/profiles_settings.xml          |  64 +++
 .../style/rmq_checkstyle.xml                       | 135 +++++
 .../style/rmq_codeStyle.xml                        | 157 ++++++
 rocketmq-spring-boot-starter/pom.xml               |  51 ++
 rocketmq-spring-boot/README.md                     |   7 +
 rocketmq-spring-boot/pom.xml                       | 104 ++++
 .../rocketmq/spring/annotation/ConsumeMode.java    |  30 +
 .../rocketmq/spring/annotation/MessageModel.java   |  33 ++
 .../spring/annotation/RocketMQMessageListener.java |  72 +++
 .../annotation/RocketMQTransactionListener.java    |  69 +++
 .../rocketmq/spring/annotation/SelectorType.java   |  33 ++
 .../config/ListenerContainerConfiguration.java     | 133 +++++
 .../spring/config/RocketMQAutoConfiguration.java   | 104 ++++
 .../spring/config/RocketMQConfigUtils.java         |  29 +
 .../rocketmq/spring/config/RocketMQProperties.java | 144 +++++
 .../RocketMQTransactionAnnotationProcessor.java    | 110 ++++
 .../rocketmq/spring/config/TransactionHandler.java |  75 +++
 .../spring/config/TransactionHandlerRegistry.java  |  50 ++
 .../rocketmq/spring/core/RocketMQListener.java     |  22 +
 .../core/RocketMQLocalTransactionListener.java     |  25 +
 .../spring/core/RocketMQLocalTransactionState.java |  24 +
 .../RocketMQPushConsumerLifecycleListener.java     |  24 +
 .../rocketmq/spring/core/RocketMQTemplate.java     | 609 +++++++++++++++++++++
 .../support/DefaultRocketMQListenerContainer.java  | 423 ++++++++++++++
 .../support/RocketMQConsumerLifecycleListener.java |  22 +
 .../rocketmq/spring/support/RocketMQHeaders.java   |  34 ++
 .../spring/support/RocketMQListenerContainer.java  |  30 +
 .../rocketmq/spring/support/RocketMQUtil.java      | 168 ++++++
 .../src/main/resources/META-INF/spring.factories   |   2 +
 .../config/RocketMQAutoConfigurationTest.java      |  92 ++++
 .../rocketmq/spring/support/RocketMQUtilTest.java  |  37 ++
 style/copyright/Apache.xml                         |  23 +
 style/copyright/profiles_settings.xml              |  64 +++
 style/rmq_checkstyle.xml                           | 135 +++++
 style/rmq_codeStyle.xml                            | 157 ++++++
 60 files changed, 5291 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..06bb326
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+.idea
+.classpath
+.project
+.settings/
+target/
+*.log*
+*.iml
+.idea/
+*.versionsBackup
+!NOTICE-BIN
+!LICENSE-BIN
+.DS_Store
+.vscode
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7a4a3ea
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..f07078d
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+Apache RocketMQ
+Copyright 2016-2018 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
index 1ce682f..9ca1362 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,277 @@
-# rocketmq-spring
+# rocketmq-spring-boot
+
+[中文](./README_zh_CN.md)
+
+[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
+
+## Introduction
+
+This is a sub-repo of RocketMQ TLP (http://rocketmq.apache.org/), It aims to help developers quickly integrate [RocketMQ](http://rocketmq.apache.org/) in [Spring Boot](http://projects.spring.io/spring-boot/). Support the Spring Message specification to facilitate developers to quickly switch from other MQ to RocketMQ.
+
+## How To Contribute
+
+We are always very happy to have contributions, whether for trivial cleanups or big new features. Please see the RocketMQ main website to read [details](http://rocketmq.apache.org/docs/how-to-contribute/)
+
+
+## Prerequisites
+- JDK 1.8 and above
+- [Maven](http://maven.apache.org/) 3.0 and above
+
+## Build and Install with local maven repository
+
+```
+  mvn clean install
+```
+
+## Features:
+
+- [x] synchronous transmission
+- [x] synchronous ordered transmission
+- [x] asynchronous transmission
+- [x] asynchronous ordered transmission
+- [x] orderly consume
+- [x] concurrently consume(broadcasting/clustering)
+- [x] one-way transmission
+- [x] transaction transmission
+- [ ] pull consume
+
+## Quick Start
+
+Please see the complete sample [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples)
+
+Note: Current RELEASE.VERSION=2.0.0
+
+```xml
+<!--add dependency in pom.xml-->
+<dependency>
+    <groupId>org.apache.rocketmq</groupId>
+    <artifactId>rocketmq-spring-boot-starter</artifactId>
+    <version>${RELEASE.VERSION}</version>
+</dependency>
+```
+
+### Produce Message
+
+```properties
+## application.properties
+spring.rocketmq.nameServer=127.0.0.1:9876
+spring.rocketmq.producer.group=my-group
+```
+
+> Note:
+> 
+> Maybe you need change `127.0.0.1:9876` with your real NameServer address for RocketMQ
+
+```java
+@SpringBootApplication
+public class ProducerApplication implements CommandLineRunner{
+    @Resource
+    private RocketMQTemplate rocketMQTemplate;
+    
+    public static void main(String[] args){
+        SpringApplication.run(ProducerApplication.class, args);
+    }
+    
+    public void run(String... args) throws Exception {
+        rocketMQTemplate.convertAndSend("test-topic-1", "Hello, World!");
+        rocketMQTemplate.send("test-topic-1", MessageBuilder.withPayload("Hello, World! I'm from spring message").build());
+        rocketMQTemplate.convertAndSend("test-topic-2", new OrderPaidEvent("T_001", new BigDecimal("88.00")));
+        
+//        rocketMQTemplate.destroy(); // notes:  once rocketMQTemplate be destroyed, you can not send any message again with this rocketMQTemplate
+    }
+    
+    @Data
+    @AllArgsConstructor
+    public class OrderPaidEvent implements Serializable{
+        private String orderId;
+        
+        private BigDecimal paidMoney;
+    }
+}
+```
+
+> More relevant configurations for producing:
+>
+> ```properties
+> spring.rocketmq.producer.retryTimesWhenSendAsyncFailed=0
+> spring.rocketmq.producer.sendMessageTimeout=300000
+> spring.rocketmq.producer.compressMessageBodyOverHowmuch=4096
+> spring.rocketmq.producer.maxMessageSize=4194304
+> spring.rocketmq.producer.retryAnotherBrokerWhenNotStoreOk=false
+> spring.rocketmq.producer.retryTimesWhenSendFailed=2
+> ```
+
+
+### Send message in transaction and implement local check Listener
+```java
+@SpringBootApplication
+public class ProducerApplication implements CommandLineRunner{
+    @Resource
+    private RocketMQTemplate rocketMQTemplate;
+
+    public static void main(String[] args){
+        SpringApplication.run(ProducerApplication.class, args);
+    }
+
+    public void run(String... args) throws Exception {
+        try {
+            // Build a SpringMessage for sending in transaction
+            Message msg = MessageBuilder.withPayload(..)...
+            // In sendMessageInTransaction(), the first parameter transaction name ("test")
+            // must be same with the @RocketMQTransactionListener's member field 'transName'
+            rocketMQTemplate.sendMessageInTransaction("test", "test-topic" msg, null);
+        } catch (MQClientException e) {
+            e.printStackTrace(System.out);
+        }
+    }
+
+    // Define transaction listener with the annotation @RocketMQTransactionListener
+    @RocketMQTransactionListener(transName="test")
+    class TransactionListenerImpl implements RocketMQLocalTransactionListener {
+          @Override
+          public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
+            // ... local transaction process, return bollback, commit or unknown
+            return RocketMQLocalTransactionState.UNKNOWN;
+          }
+
+          @Override
+          public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
+            // ... check transaction status and return bollback, commit or unknown
+            return RocketMQLocalTransactionState.COMMIT;
+          }
+    }
+}
+```
+
+### Consume Message
+
+```properties
+## application.properties
+spring.rocketmq.nameServer=127.0.0.1:9876
+```
+
+> Note:
+> 
+> Maybe you need change `127.0.0.1:9876` with your real NameServer address for RocketMQ
+
+```java
+@SpringBootApplication
+public class ConsumerApplication{
+    
+    public static void main(String[] args){
+        SpringApplication.run(ConsumerApplication.class, args);
+    }
+    
+    @Slf4j
+    @Service
+    @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1")
+    public class MyConsumer1 implements RocketMQListener<String>{
+        public void onMessage(String message) {
+            log.info("received message: {}", message);
+        }
+    }
+    
+    @Slf4j
+    @Service
+    @RocketMQMessageListener(topic = "test-topic-2", consumerGroup = "my-consumer_test-topic-2")
+    public class MyConsumer2 implements RocketMQListener<OrderPaidEvent>{
+        public void onMessage(OrderPaidEvent orderPaidEvent) {
+            log.info("received orderPaidEvent: {}", orderPaidEvent);
+        }
+    }
+}
+```
+
+> More relevant configurations for consuming:
+>
+> see: [RocketMQMessageListener](src/main/java/org/apache/rocketmq/spring/starter/annotation/RocketMQMessageListener.java)
+
+
+## FAQ
+
+1. How to connected many `nameserver` on production environment?
+
+    `spring.rocketmq.nameServer` support the configuration of multiple `nameserver`, separated by `;`. For example: `172.19.0.1: 9876; 172.19.0.2: 9876`
+
+1. When was `rocketMQTemplate` destroyed?
+
+    Developers do not need to manually execute the `rocketMQTemplate.destroy ()` method when using `rocketMQTemplate` to send a message in the project, and` rocketMQTemplate` will be destroyed automatically when the spring container is destroyed.
+
+1. start exception:`Caused by: org.apache.rocketmq.client.exception.MQClientException: The consumer group[xxx] has been created before, specify another name please`
+
+   RocketMQ in the design do not want a consumer to deal with multiple types of messages at the same time, so the same `consumerGroup` consumer responsibility should be the same, do not do different things (that is, consumption of multiple topics). Suggested `consumerGroup` and` topic` one correspondence.
+    
+1. How is the message content body being serialized and deserialized?
+
+    RocketMQ's message body is stored as `byte []`. When the business system message content body if it is `java.lang.String` type, unified in accordance with` utf-8` code into `byte []`; If the business system message content is not `java.lang.String` Type, then use [jackson-databind](https://github.com/FasterXML/jackson-databind) serialized into the `JSON` format string, and then unified in accordance with` utf-8` code into `byte [] `.
+    
+1. How do I specify the `tags` for topic?
+
+    RocketMQ best practice recommended: an application as much as possible with one Topic, the message sub-type with `tags` to identify,` tags` can be set by the application free.
+    
+    When you use `rocketMQTemplate` to send a message, set the destination of the message by setting the` destination` parameter of the send method. The `destination` format is `topicName:tagName`, `:` Precedes the name of the topic, followed by the `tags` name.
+    
+    > Note:
+    >
+    > `tags` looks a complex, but when sending a message , the destination can only specify one topic under a `tag`, can not specify multiple.
+    
+1. How do I set the message's `key` when sending a message?
+
+    You can send a message by overloading method like `xxxSend(String destination, Message<?> msg, ...)`, setting `headers` of `msg`. for example:
+    
+    ```java
+    Message<?> message = MessageBuilder.withPayload(payload).setHeader(MessageConst.PROPERTY_KEYS, msgId).build();
+    rocketMQTemplate.send("topic-test", message);
+    ```
+
+    Similarly, you can also set the message `FLAG`,` WAIT_STORE_MSG_OK` and some other user-defined other header information according to the above method.
+    
+    > Note:
+    >
+    > In the case of converting Spring's Message to RocketMQ's Message, to prevent the `header` information from conflicting with RocketMQ's system properties, the prefix `USERS_` was added in front of all `header` names. So if you want to get a custom message header when consuming, please pass through the key at the beginning of `USERS_` in the header.
+    
+1. When consume message, in addition to get the message `payload`, but also want to get RocketMQ message of other system attributes, how to do?
+
+    Consumers in the realization of `RocketMQListener` interface, only need to be generic for the` MessageExt` can, so in the `onMessage` method will receive RocketMQ native 'MessageExt` message.
+    
+    ```java
+    @Slf4j
+    @Service
+    @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1")
+    public class MyConsumer2 implements RocketMQListener<MessageExt>{
+        public void onMessage(MessageExt messageExt) {
+            log.info("received messageExt: {}", messageExt);
+        }
+    }
+    ```
+    
+1. How do I specify where consumers start consuming messages?
+
+    The default consume offset please refer: [RocketMQ FAQ](http://rocketmq.apache.org/docs/faq/).
+    To customize the consumer's starting location, simply add a `RocketMQPushConsumerLifecycleListener` interface implementation to the consumer class. Examples are as follows:
+    
+    ```java
+    @Slf4j
+    @Service
+    @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1")
+    public class MyConsumer1 implements RocketMQListener<String>, RocketMQPushConsumerLifecycleListener {
+        @Override
+        public void onMessage(String message) {
+            log.info("received message: {}", message);
+        }
+    
+        @Override
+        public void prepareStart(final DefaultMQPushConsumer consumer) {
+            // set consumer consume message from now
+            consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP);
+            consumer.setConsumeTimestamp(UtilAll.timeMillisToHumanString3(System.currentTimeMillis()));
+        }
+    }
+    ```
+    
+    Similarly, any other configuration on `DefaultMQPushConsumer` can be done in the same way as above.
+
+
+1. How do I send transactional messages?
+   It needs two steps on client side: a) Define a class which is annotated with @RocketMQTransactionListener and implements RocketMQLocalTransactionListener interface, in which, the executeLocalTransaction() and checkLocalTransaction() methods are implemented;
+   b) Invoke the sendMessageInTransaction() method with the RocketMQTemplate API. Note: The first parameter of this method is correlated with the txProducerGroup attribute of @RocketMQTransactionListener. It can be null if using the default transaction producer group.
diff --git a/README_zh_CN.md b/README_zh_CN.md
new file mode 100644
index 0000000..c7c928a
--- /dev/null
+++ b/README_zh_CN.md
@@ -0,0 +1,268 @@
+# rocketmq-spring-boot
+
+[English](./README.md)
+
+[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
+
+帮助开发者在[Spring Boot](http://projects.spring.io/spring-boot/)中快速集成[RocketMQ](http://rocketmq.apache.org/)。支持Spring Message规范,方便开发者从其它MQ快速切换到RocketMQ。
+
+## 如何贡献和帮助社区
+
+我们永远欢迎开发者的帮助来使这个项目更加完善,无论是小的文档还是大的功能新特性,请参考RocketMQ的主站了解[细节](http://rocketmq.apache.org/docs/how-to-contribute/)
+
+## 前提条件
+- JDK 1.8 and above
+- [Maven](http://maven.apache.org/) 3.0 and above
+
+功能特性:
+
+- [x] 同步发送
+- [x] 同步顺序发送
+- [x] 异步发送
+- [x] 异步顺序发送
+- [x] 顺序消费
+- [x] 并发消费(广播/集群)
+- [x] one-way方式发送
+- [x] 事务方式发送
+- [ ] pull消费
+
+## Quick Start
+
+下面列出来了一些关键点,完整的示例请参考: [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples)
+
+注意:当前的RELEASE.VERSION=2.0.0
+
+```xml
+<!--在pom.xml中添加依赖-->
+<dependency>
+    <groupId>org.apache.rocketmq</groupId>
+    <artifactId>rocketmq-spring-boot-starter</artifactId>
+    <version>${RELEASE.VERSION}</version>
+</dependency>
+```
+
+### 发送消息
+
+```properties
+## application.properties
+spring.rocketmq.nameServer=127.0.0.1:9876
+spring.rocketmq.producer.group=my-group
+```
+
+> 注意:
+> 
+> 请将上述示例配置中的`127.0.0.1:9876`替换成真实RocketMQ的NameServer地址与端口
+
+```java
+@SpringBootApplication
+public class ProducerApplication implements CommandLineRunner{
+    @Resource
+    private RocketMQTemplate rocketMQTemplate;
+    
+    public static void main(String[] args){
+        SpringApplication.run(ProducerApplication.class, args);
+    }
+    
+    public void run(String... args) throws Exception {
+        rocketMQTemplate.convertAndSend("test-topic-1", "Hello, World!");
+        rocketMQTemplate.send("test-topic-1", MessageBuilder.withPayload("Hello, World! I'm from spring message").build());
+        rocketMQTemplate.convertAndSend("test-topic-2", new OrderPaidEvent("T_001", new BigDecimal("88.00")));
+        
+//        rocketMQTemplate.destroy(); // notes:  once rocketMQTemplate be destroyed, you can not send any message again with this rocketMQTemplate
+    }
+    
+    @Data
+    @AllArgsConstructor
+    public class OrderPaidEvent implements Serializable{
+        private String orderId;
+        
+        private BigDecimal paidMoney;
+    }
+}
+```
+
+### 在发送客户端发送事务性消息并且实现回查Listener
+```java
+@SpringBootApplication
+public class ProducerApplication implements CommandLineRunner{
+    @Resource
+    private RocketMQTemplate rocketMQTemplate;
+
+    public static void main(String[] args){
+        SpringApplication.run(ProducerApplication.class, args);
+    }
+
+    public void run(String... args) throws Exception {
+        try {
+            // Build a SpringMessage for sending in transaction
+            Message msg = MessageBuilder.withPayload(..)...
+            // In sendMessageInTransaction(), the first parameter transaction name ("test")
+            // must be same with the @RocketMQTransactionListener's member field 'transName'
+            rocketMQTemplate.sendMessageInTransaction("test", "test-topic" msg, null);
+        } catch (MQClientException e) {
+            e.printStackTrace(System.out);
+        }
+    }
+
+    // Define transaction listener with the annotation @RocketMQTransactionListener
+    @RocketMQTransactionListener(transName="test")
+    class TransactionListenerImpl implements RocketMQLocalTransactionListener {
+          @Override
+          public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
+            // ... local transaction process, return bollback, commit or unknown
+            return RocketMQLocalTransactionState.UNKNOWN;
+          }
+
+          @Override
+          public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
+            // ... check transaction status and return bollback, commit or unknown
+            return RocketMQLocalTransactionState.COMMIT;
+          }
+    }
+}
+```
+
+> 更多发送相关配置
+>
+> ```properties
+> spring.rocketmq.producer.retryTimesWhenSendAsyncFailed=0
+> spring.rocketmq.producer.sendMessageTimeout=300000
+> spring.rocketmq.producer.compressMessageBodyOverHowmuch=4096
+> spring.rocketmq.producer.maxMessageSize=4194304
+> spring.rocketmq.producer.retryAnotherBrokerWhenNotStoreOk=false
+> spring.rocketmq.producer.retryTimesWhenSendFailed=2
+> ```
+
+
+### 接收消息
+
+```properties
+## application.properties
+spring.rocketmq.nameServer=127.0.0.1:9876
+```
+
+> 注意:
+> 
+> 请将上述示例配置中的`127.0.0.1:9876`替换成真实RocketMQ的NameServer地址与端口
+
+```java
+@SpringBootApplication
+public class ConsumerApplication{
+    
+    public static void main(String[] args){
+        SpringApplication.run(ConsumerApplication.class, args);
+    }
+    
+    @Slf4j
+    @Service
+    @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1")
+    public class MyConsumer1 implements RocketMQListener<String>{
+        public void onMessage(String message) {
+            log.info("received message: {}", message);
+        }
+    }
+    
+    @Slf4j
+    @Service
+    @RocketMQMessageListener(topic = "test-topic-2", consumerGroup = "my-consumer_test-topic-2")
+    public class MyConsumer2 implements RocketMQListener<OrderPaidEvent>{
+        public void onMessage(OrderPaidEvent orderPaidEvent) {
+            log.info("received orderPaidEvent: {}", orderPaidEvent);
+        }
+    }
+}
+```
+
+
+> 更多消费相关配置
+>
+> see: [RocketMQMessageListener](src/main/java/org/apache/rocketmq/spring/starter/annotation/RocketMQMessageListener.java) 
+
+
+## FAQ
+
+1. 生产环境有多个`nameserver`该如何连接?
+
+   `spring.rocketmq.nameServer`支持配置多个`nameserver`地址,采用`;`分隔即可。例如:`172.19.0.1:9876;172.19.0.2:9876`
+
+1. `rocketMQTemplate`在什么时候被销毁?
+
+    开发者在项目中使用`rocketMQTemplate`发送消息时,不需要手动执行`rocketMQTemplate.destroy()`方法, `rocketMQTemplate`会在spring容器销毁时自动销毁。
+
+1. 启动报错:`Caused by: org.apache.rocketmq.client.exception.MQClientException: The consumer group[xxx] has been created before, specify another name please`
+
+    RocketMQ在设计时就不希望一个消费者同时处理多个类型的消息,因此同一个`consumerGroup`下的consumer职责应该是一样的,不要干不同的事情(即消费多个topic)。建议`consumerGroup`与`topic`一一对应。
+    
+1. 发送的消息内容体是如何被序列化与反序列化的?
+
+    RocketMQ的消息体都是以`byte[]`方式存储。当业务系统的消息内容体如果是`java.lang.String`类型时,统一按照`utf-8`编码转成`byte[]`;如果业务系统的消息内容为非`java.lang.String`类型,则采用[jackson-databind](https://github.com/FasterXML/jackson-databind)序列化成`JSON`格式的字符串之后,再统一按照`utf-8`编码转成`byte[]`。
+    
+1. 如何指定topic的`tags`?
+
+    RocketMQ的最佳实践中推荐:一个应用尽可能用一个Topic,消息子类型用`tags`来标识,`tags`可以由应用自由设置。
+    在使用`rocketMQTemplate`发送消息时,通过设置发送方法的`destination`参数来设置消息的目的地,`destination`的格式为`topicName:tagName`,`:`前面表示topic的名称,后面表示`tags`名称。
+    
+    > 注意:
+    >
+    > `tags`从命名来看像是一个复数,但发送消息时,目的地只能指定一个topic下的一个`tag`,不能指定多个。
+    
+1. 发送消息时如何设置消息的`key`?
+
+    可以通过重载的`xxxSend(String destination, Message<?> msg, ...)`方法来发送消息,指定`msg`的`headers`来完成。示例:
+    
+    ```java
+    Message<?> message = MessageBuilder.withPayload(payload).setHeader(MessageConst.PROPERTY_KEYS, msgId).build();
+    rocketMQTemplate.send("topic-test", message);
+    ```
+
+    同理还可以根据上面的方式来设置消息的`FLAG`、`WAIT_STORE_MSG_OK`以及一些用户自定义的其它头信息。
+    
+    > 注意:
+    >
+    > 在将Spring的Message转化为RocketMQ的Message时,为防止`header`信息与RocketMQ的系统属性冲突,在所有`header`的名称前面都统一添加了前缀`USERS_`。因此在消费时如果想获取自定义的消息头信息,请遍历头信息中以`USERS_`开头的key即可。
+    
+1. 消费消息时,除了获取消息`payload`外,还想获取RocketMQ消息的其它系统属性,需要怎么做?
+
+    消费者在实现`RocketMQListener`接口时,只需要起泛型为`MessageExt`即可,这样在`onMessage`方法将接收到RocketMQ原生的`MessageExt`消息。
+    
+    ```java
+    @Slf4j
+    @Service
+    @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1")
+    public class MyConsumer2 implements RocketMQListener<MessageExt>{
+        public void onMessage(MessageExt messageExt) {
+            log.info("received messageExt: {}", messageExt);
+        }
+    }
+    ```
+    
+1. 如何指定消费者从哪开始消费消息,或开始消费的位置?
+
+    消费者默认开始消费的位置请参考:[RocketMQ FAQ](http://rocketmq.apache.org/docs/faq/)。
+    若想自定义消费者开始的消费位置,只需在消费者类添加一个`RocketMQPushConsumerLifecycleListener`接口的实现即可。 示例如下:
+    
+    ```java
+    @Slf4j
+    @Service
+    @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1")
+    public class MyConsumer1 implements RocketMQListener<String>, RocketMQPushConsumerLifecycleListener {
+        @Override
+        public void onMessage(String message) {
+            log.info("received message: {}", message);
+        }
+    
+        @Override
+        public void prepareStart(final DefaultMQPushConsumer consumer) {
+            // set consumer consume message from now
+            consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP);
+            consumer.setConsumeTimestamp(UtilAll.timeMillisToHumanString3(System.currentTimeMillis()));
+        }
+    }
+    ```
+    
+    同理,任何关于`DefaultMQPushConsumer`的更多其它其它配置,都可以采用上述方式来完成。
+    
+1. 如何发送事务消息(即半消息支持分布式事务)?
+	在客户端,首先用户需要实现RocketMQLocalTransactionListener接口,并在接口类上注解声明@RocketMQTransactionListener,实现确认和回查方法;然后再使用资源模板RocketMQTemplate,
+	调用方法sendMessageInTransaction()来进行消息的发布。 注意:这个方法通过指定发送者组名与具体的声明了txProducerGroup的TransactionListener进行关联,您也可以不指定这个值,从而使用默认的事务发送者组。
+    
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..7ca40cc
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,80 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.rocketmq</groupId>
+    <artifactId>rocketmq-spring-boot-build</artifactId>
+    <version>2.0.0</version>
+    <packaging>pom</packaging>
+
+    <name>RocketMQ Spring Boot Build</name>
+    <description>Build for Apache RocketMQ Spring Boot Support</description>
+    <url>https://github.com/apache/rocketmq-spring</url>
+
+    <organization>
+        <name>Apache Software Foundation</name>
+        <url>http://www.apache.org</url>
+    </organization>
+
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>
+            <comments>A business-friendly OSS license</comments>
+        </license>
+    </licenses>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <version>2.17</version>
+                <executions>
+                    <execution>
+                        <id>validate</id>
+                        <phase>validate</phase>
+                        <configuration>
+                            <excludes>src/main/resources</excludes>
+                            <configLocation>style/rmq_checkstyle.xml</configLocation>
+                            <encoding>UTF-8</encoding>
+                            <consoleOutput>true</consoleOutput>
+                            <failsOnError>true</failsOnError>
+                        </configuration>
+                        <goals>
+                            <goal>check</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <modules>
+        <module>rocketmq-spring-boot-parent</module>
+        <module>rocketmq-spring-boot</module>
+        <module>rocketmq-spring-boot-starter</module>
+        <!-- Note: The samples need to mvn compiple in its own directory
+                <module>rocketmq-spring-boot-samples</module>
+        -->
+    </modules>
+</project>
diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml
new file mode 100644
index 0000000..005c2cb
--- /dev/null
+++ b/rocketmq-spring-boot-parent/pom.xml
@@ -0,0 +1,177 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.rocketmq</groupId>
+        <artifactId>rocketmq-spring-boot-build</artifactId>
+        <version>2.0.0</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>rocketmq-spring-boot-parent</artifactId>
+    <packaging>pom</packaging>
+
+    <name>RocketMQ Spring Boot Parent</name>
+    <description>Parent package for Apache RocketMQ Spring Boot Support</description>
+    <url>https://github.com/apache/rocketmq-spring</url>
+
+    <properties>
+        <project.rootdir>${project.basedir}/..</project.rootdir>
+        <spring.boot.version>2.0.5.RELEASE</spring.boot.version>
+        <spring.version>5.1.0.RELEASE</spring.version>
+
+        <rocketmq.spring.boot.version>2.0.0</rocketmq.spring.boot.version>
+
+        <rocketmq-version>4.3.2</rocketmq-version>
+        <slf4j.version>1.6.1</slf4j.version>
+        <jackson.version>2.9.7</jackson.version>
+
+        <java.version>1.8</java.version>
+        <resource.delimiter>@</resource.delimiter>
+        <!-- Delimiter that doesn't clash with Spring ${} placeholders -->
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <maven.compiler.source>${java.version}</maven.compiler.source>
+        <maven.compiler.target>${java.version}</maven.compiler.target>
+        <additionalparam>-Xdoclint:none</additionalparam>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot</artifactId>
+                <version>${spring.boot.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-autoconfigure</artifactId>
+                <version>${spring.boot.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-autoconfigure-processor</artifactId>
+                <version>${spring.boot.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-test</artifactId>
+                <version>${spring.boot.version}</version>
+                <scope>test</scope>
+            </dependency>
+
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter</artifactId>
+                <version>${spring.boot.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-validation</artifactId>
+                <version>${spring.boot.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.rocketmq</groupId>
+                <artifactId>rocketmq-spring-boot</artifactId>
+                <version>${rocketmq.spring.boot.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.rocketmq</groupId>
+                <artifactId>rocketmq-client</artifactId>
+                <version>${rocketmq-version}</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.slf4j</groupId>
+                        <artifactId>slf4j-api</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-messaging</artifactId>
+                <version>${spring.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-core</artifactId>
+                <version>${spring.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-context</artifactId>
+                <version>${spring.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-aop</artifactId>
+                <version>${spring.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>${slf4j.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-databind</artifactId>
+                <version>${jackson.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <version>2.17</version>
+                <executions>
+                    <execution>
+                        <id>validate</id>
+                        <phase>validate</phase>
+                        <configuration>
+                            <excludes>src/main/resources</excludes>
+                            <configLocation>style/rmq_checkstyle.xml</configLocation>
+                            <encoding>UTF-8</encoding>
+                            <consoleOutput>true</consoleOutput>
+                            <failsOnError>true</failsOnError>
+                        </configuration>
+                        <goals>
+                            <goal>check</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/rocketmq-spring-boot-samples/LICENSE b/rocketmq-spring-boot-samples/LICENSE
new file mode 100644
index 0000000..7a4a3ea
--- /dev/null
+++ b/rocketmq-spring-boot-samples/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/rocketmq-spring-boot-samples/README.md b/rocketmq-spring-boot-samples/README.md
new file mode 100644
index 0000000..555f3bf
--- /dev/null
+++ b/rocketmq-spring-boot-samples/README.md
@@ -0,0 +1,38 @@
+# rocketmq-spring-boot-samples
+
+[中文](./README_zh_CN.md)
+
+[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
+
+It's a demo project for how to use [rocketmq-spring-boot](https://github.com/apache/rocketmq-spring)
+
+> Note:
+>
+> If `org.apache.rocketmq:rocketmq-spring-boot-starter:${RELEASE.VERSION}` not exists in maven central repository, before you run this demo, you must git clone [rocketmq-spring-boot](https://github.com/apache/rocketmq-spring) and use `mvn clean install` build it by yourself.
+
+Run the test case locally
+1. build and install the rocketmq-spring-boot-starter
+
+2. startup rocketmq according to quick-start, verify the namesvr and broker startup correctly, Note: DON'T do "Shutdown Servers" step.
+http://rocketmq.apache.org/docs/quick-start/
+
+3. create topics for the demo test cases
+```
+bash bin/mqadmin updateTopic -c DefaultCluster -t string-topic
+bash bin/mqadmin updateTopic -c DefaultCluster -t order-paid-topic
+bash bin/mqadmin updateTopic -c DefaultCluster -t message-ext-topic
+bash bin/mqadmin updateTopic -c DefaultCluster -t spring-transaction-topic
+```
+4. run tests
+
+```
+# open a terminal, run produce
+cd rocketmq-produce-demo
+mvn clean package
+java -jar target/rocketmq-produce-demo-0.0.1-SNAPSHOT.jar
+
+# open another terminal, run consume
+cd rocketmq-consume-demo
+mvn clean package
+java -jar target/rocketmq-consume-demo-0.0.1-SNAPSHOT.jar
+```
diff --git a/rocketmq-spring-boot-samples/README_zh_CN.md b/rocketmq-spring-boot-samples/README_zh_CN.md
new file mode 100644
index 0000000..099d3b8
--- /dev/null
+++ b/rocketmq-spring-boot-samples/README_zh_CN.md
@@ -0,0 +1,48 @@
+# rocketmq-spring-boot-samples
+
+[English](./README.md)
+
+[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
+
+这里是一个使用rocketmq-spring-boot-starter的列子。 [rocketmq-spring-boot](https://github.com/apache/rocketmq-spring)
+
+> 注意:
+>
+> 如果这个dependency: `org.apache.rocketmq:rocketmq-spring-boot-starter:${RELEASE.VERSION}`在maven中心库不存在, 需要开发者在本地build并安装到本地maven库,执行如下步骤:
+```
+ git clone https://github.com/apache/rocketmq-spring
+ cd rocketmq-spring
+ mvn clean install
+```
+
+## 在本地运行这个测试例子
+
+1. 如上面注意项所述,需要开发者在本地build并安装rocketmq-spring-boot-starter
+
+2. 根据RocketMQ官网的quick-start来启动NameServer和Broker,并验证是否启动正确。注意: 测试期间不要停止Broker或者NameServer
+http://rocketmq.apache.org/docs/quick-start/
+
+3. 创建测试例子所需要的Topic
+```
+cd YOUR_ROCKETMQ_HOME
+
+bash bin/mqadmin updateTopic -c DefaultCluster -t string-topic
+bash bin/mqadmin updateTopic -c DefaultCluster -t order-paid-topic
+bash bin/mqadmin updateTopic -c DefaultCluster -t message-ext-topic
+bash bin/mqadmin updateTopic -c DefaultCluster -t spring-transaction-topic
+```
+
+4. 编译并运行测试例子
+
+```
+# 打开一个终端窗口,编译并启动发送端
+cd rocketmq-produce-demo
+mvn clean package
+java -jar target/rocketmq-produce-demo-0.0.1-SNAPSHOT.jar
+
+# 打开另一个终端窗口,编译并启动消费端
+cd rocketmq-consume-demo
+mvn clean package
+java -jar target/rocketmq-consume-demo-0.0.1-SNAPSHOT.jar
+```
+结合测试代码,观察窗口中消息的发送和接收情况
diff --git a/rocketmq-spring-boot-samples/pom.xml b/rocketmq-spring-boot-samples/pom.xml
new file mode 100644
index 0000000..7b5eaa5
--- /dev/null
+++ b/rocketmq-spring-boot-samples/pom.xml
@@ -0,0 +1,89 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.apache.rocketmq</groupId>
+    <artifactId>rocketmq-spring-boot-samples</artifactId>
+    <packaging>pom</packaging>
+    <version>0.0.1-SNAPSHOT</version>
+    
+    <name>RocketMQ Spring Boot Samples</name>
+    <description>Samples for RocketMQ Spring Boot</description>
+    <url>https://github.com/apache/rocketmq-spring</url>
+    
+    <modules>
+        <module>rocketmq-produce-demo</module>
+        <module>rocketmq-consume-demo</module>
+    </modules>
+
+    <properties>
+        <rocketmq-spring-boot-starter-version>2.0.0</rocketmq-spring-boot-starter-version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.rocketmq</groupId>
+            <artifactId>rocketmq-spring-boot-starter</artifactId>
+            <version>${rocketmq-spring-boot-starter-version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <version>2.17</version>
+                <executions>
+                    <execution>
+                        <id>validate</id>
+                        <phase>validate</phase>
+                        <configuration>
+                            <skip>${disable.checks}</skip>
+                            <excludes>src/main/resources</excludes>
+                            <configLocation>style/rmq_checkstyle.xml</configLocation>
+                            <encoding>UTF-8</encoding>
+                            <consoleOutput>true</consoleOutput>
+                            <failsOnError>true</failsOnError>
+                        </configuration>
+                        <goals>
+                            <goal>check</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.1.0.RELEASE</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml b/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml
new file mode 100644
index 0000000..4093170
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml
@@ -0,0 +1,31 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.rocketmq</groupId>
+        <artifactId>rocketmq-spring-boot-samples</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+    
+    <artifactId>rocketmq-consume-demo</artifactId>
+
+</project>
\ No newline at end of file
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerApplication.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerApplication.java
new file mode 100644
index 0000000..e4fbc8c
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerApplication.java
@@ -0,0 +1,33 @@
+/*
+ * 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.rocketmq.samples.springboot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * ConsumerApplication
+ */
+@SpringBootApplication
+public class ConsumerApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(ConsumerApplication.class, args);
+    }
+}
+
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/Checker.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/Checker.java
new file mode 100644
index 0000000..608df1b
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/Checker.java
@@ -0,0 +1,44 @@
+/*
+ * 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.rocketmq.samples.springboot.consumer;
+
+import org.apache.rocketmq.client.producer.LocalTransactionState;
+import org.apache.rocketmq.client.producer.TransactionListener;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageExt;
+
+/**
+ * Note: This is a nagitive testing. It aims to tell user the fact that
+ * the @RocketMQTransactionListener can not be used on consumer side!!!
+ *
+ * <p>How to try it? just uncomment the annotation declaration, then compile
+ * and run the consumer, it will fail to start.
+ */
+
+//@RocketMQTransactionListener
+public class Checker implements TransactionListener {
+    @Override
+    public LocalTransactionState executeLocalTransaction(Message message, Object o) {
+        return null;
+    }
+
+    @Override
+    public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
+        return null;
+    }
+}
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/MessageExtConsumer.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/MessageExtConsumer.java
new file mode 100644
index 0000000..59ef263
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/MessageExtConsumer.java
@@ -0,0 +1,46 @@
+/*
+ * 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.rocketmq.samples.springboot.consumer;
+
+import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
+import org.apache.rocketmq.common.UtilAll;
+import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener;
+import org.springframework.stereotype.Service;
+
+/**
+ * MessageExtConsumer, consume listener impl class.
+ */
+@Service
+@RocketMQMessageListener(topic = "message-ext-topic", selectorExpression = "tag1", consumerGroup = "${spring.application.name}-message-ext-consumer")
+public class MessageExtConsumer implements RocketMQListener<MessageExt>, RocketMQPushConsumerLifecycleListener {
+    @Override
+    public void onMessage(MessageExt message) {
+        System.out.printf("------- MessageExtConsumer received message, msgId: %s, body:%s \n", message.getMsgId(), new String(message.getBody()));
+    }
+
+    @Override
+    public void prepareStart(DefaultMQPushConsumer consumer) {
+        // set consumer consume message from now
+        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP);
+        consumer.setConsumeTimestamp(UtilAll.timeMillisToHumanString3(System.currentTimeMillis()));
+    }
+}
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/OrderPaidEventConsumer.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/OrderPaidEventConsumer.java
new file mode 100644
index 0000000..774cd23
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/OrderPaidEventConsumer.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.rocketmq.samples.springboot.consumer;
+
+import org.apache.rocketmq.samples.springboot.domain.OrderPaidEvent;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.springframework.stereotype.Service;
+
+/**
+ * OrderPaidEventConsumer
+ */
+@Service
+@RocketMQMessageListener(topic = "${spring.rocketmq.orderTopic}", consumerGroup = "order-paid-consumer")
+public class OrderPaidEventConsumer implements RocketMQListener<OrderPaidEvent> {
+
+    @Override
+    public void onMessage(OrderPaidEvent orderPaidEvent) {
+        System.out.printf("------- OrderPaidEventConsumer received: %s \n", orderPaidEvent);
+    }
+}
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumer.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumer.java
new file mode 100644
index 0000000..370e847
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumer.java
@@ -0,0 +1,34 @@
+/*
+ * 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.rocketmq.samples.springboot.consumer;
+
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.springframework.stereotype.Service;
+
+/**
+ * RocketMQMessageListener
+ */
+@Service
+@RocketMQMessageListener(topic = "${spring.rocketmq.topic}", consumerGroup = "string_consumer")
+public class StringConsumer implements RocketMQListener<String> {
+    @Override
+    public void onMessage(String message) {
+        System.out.printf("------- StringConsumer received: %s \n", message);
+    }
+}
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringTransactionalConsumer.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringTransactionalConsumer.java
new file mode 100644
index 0000000..5eebcc8
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringTransactionalConsumer.java
@@ -0,0 +1,34 @@
+/*
+ * 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.rocketmq.samples.springboot.consumer;
+
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.springframework.stereotype.Service;
+
+/**
+ * StringTransactionalConsumer
+ */
+@Service
+@RocketMQMessageListener(topic = "${spring.rocketmq.transTopic}", consumerGroup = "string_trans_consumer")
+public class StringTransactionalConsumer implements RocketMQListener<String> {
+    @Override
+    public void onMessage(String message) {
+        System.out.printf("------- StringTransactionalConsumer received: %s \n", message);
+    }
+}
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java
new file mode 100644
index 0000000..812ab83
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.samples.springboot.domain;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * OrderPaidEvent
+ */
+public class OrderPaidEvent implements Serializable {
+    private String orderId;
+
+    private BigDecimal paidMoney;
+
+    public OrderPaidEvent() {
+    }
+
+    public OrderPaidEvent(String orderId, BigDecimal paidMoney) {
+        this.orderId = orderId;
+        this.paidMoney = paidMoney;
+    }
+
+    public String getOrderId() {
+        return orderId;
+    }
+
+    public void setOrderId(String orderId) {
+        this.orderId = orderId;
+    }
+
+    public BigDecimal getPaidMoney() {
+        return paidMoney;
+    }
+
+    public void setPaidMoney(BigDecimal paidMoney) {
+        this.paidMoney = paidMoney;
+    }
+}
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/resources/application.properties b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/resources/application.properties
new file mode 100644
index 0000000..bbdeed1
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+spring.application.name=rocketmq-consume-demo
+
+spring.rocketmq.nameServer=localhost:9876
+spring.rocketmq.topic=string-topic
+spring.rocketmq.orderTopic=order-paid-topic
+spring.rocketmq.msgExtTopic=message-ext-topic
+spring.rocketmq.transTopic=spring-transaction-topic
diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml b/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml
new file mode 100644
index 0000000..0ef364d
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml
@@ -0,0 +1,32 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.rocketmq</groupId>
+        <artifactId>rocketmq-spring-boot-samples</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>rocketmq-produce-demo</artifactId>
+
+
+</project>
\ No newline at end of file
diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerApplication.java b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerApplication.java
new file mode 100644
index 0000000..bec2450
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerApplication.java
@@ -0,0 +1,171 @@
+/*
+ * 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.rocketmq.samples.springboot;
+
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.samples.springboot.domain.OrderPaidEvent;
+import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
+import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
+import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.apache.rocketmq.spring.support.RocketMQHeaders;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessagingException;
+import org.springframework.messaging.support.MessageBuilder;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Producer, using RocketMQTemplate sends a variety of messages
+ */
+@SpringBootApplication
+public class ProducerApplication implements CommandLineRunner {
+    private static final String TX_PGROUP_NAME = "myTxProducerGroup";
+    @Resource
+    private RocketMQTemplate rocketMQTemplate;
+    @Value("${spring.rocketmq.transTopic}")
+    private String springTransTopic;
+    @Value("${spring.rocketmq.topic}")
+    private String springTopic;
+    @Value("${spring.rocketmq.orderTopic}")
+    private String orderPaidTopic;
+    @Value("${spring.rocketmq.msgExtTopic}")
+    private String msgExtTopic;
+
+    public static void main(String[] args) {
+        SpringApplication.run(ProducerApplication.class, args);
+    }
+
+    @Override
+    public void run(String... args) throws Exception {
+        // Send string
+        SendResult sendResult = rocketMQTemplate.syncSend(springTopic, "Hello, World!");
+        System.out.printf("syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult);
+
+        // Send string with spring Message
+        sendResult = rocketMQTemplate.syncSend(springTopic, MessageBuilder.withPayload("Hello, World! I'm from spring message").build());
+        System.out.printf("syncSend2 to topic %s sendResult=%s %n", springTopic, sendResult);
+
+        // Send user-defined object
+        rocketMQTemplate.asyncSend(orderPaidTopic, new OrderPaidEvent("T_001", new BigDecimal("88.00")), new SendCallback() {
+            public void onSuccess(SendResult var1) {
+                System.out.printf("async onSucess SendResult=%s %n", var1);
+            }
+
+            public void onException(Throwable var1) {
+                System.out.printf("async onException Throwable=%s %n", var1);
+            }
+
+        });
+
+        // Send message with special tag
+        rocketMQTemplate.convertAndSend(msgExtTopic + ":tag0", "I'm from tag0");  // tag0 will not be consumer-selected
+        System.out.printf("syncSend topic %s tag %s %n", msgExtTopic, "tag0");
+        rocketMQTemplate.convertAndSend(msgExtTopic + ":tag1", "I'm from tag1");
+        System.out.printf("syncSend topic %s tag %s %n", msgExtTopic, "tag1");
+
+        // Send transactional messages
+        testTransaction();
+    }
+
+
+    private void testTransaction() throws MessagingException {
+        String[] tags = new String[]{"TagA", "TagB", "TagC", "TagD", "TagE"};
+        for (int i = 0; i < 10; i++) {
+            try {
+
+                Message msg = MessageBuilder.withPayload("Hello RocketMQ " + i).
+                    setHeader(RocketMQHeaders.KEYS, "KEY_" + i).build();
+                SendResult sendResult = rocketMQTemplate.sendMessageInTransaction(TX_PGROUP_NAME,
+                    springTransTopic + ":" + tags[i % tags.length], msg, null);
+                System.out.printf("------ send Transactional msg body = %s , sendResult=%s %n",
+                    msg.getPayload(), sendResult.getSendStatus());
+
+                Thread.sleep(10);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    @RocketMQTransactionListener(txProducerGroup = TX_PGROUP_NAME)
+    class TransactionListenerImpl implements RocketMQLocalTransactionListener {
+        private AtomicInteger transactionIndex = new AtomicInteger(0);
+
+        private ConcurrentHashMap<String, Integer> localTrans = new ConcurrentHashMap<String, Integer>();
+
+        @Override
+        public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
+            String transId = (String)msg.getHeaders().get(RocketMQHeaders.TRANSACTION_ID);
+            System.out.printf("#### executeLocalTransaction is executed, msgTransactionId=%s %n",
+                transId);
+            int value = transactionIndex.getAndIncrement();
+            int status = value % 3;
+            localTrans.put(transId, status);
+            if (status == 0) {
+                // Return local transaction with success(commit), in this case,
+                // this message will not be checked in checkLocalTransaction()
+                System.out.printf("    # COMMIT # Simulating msg %s related local transaction exec succeeded! ### %n", msg.getPayload());
+                return RocketMQLocalTransactionState.COMMIT;
+            }
+
+            if (status == 1) {
+                // Return local transaction with failure(rollback) , in this case,
+                // this message will not be checked in checkLocalTransaction()
+                System.out.printf("    # ROLLBACK # Simulating %s related local transaction exec failed! %n", msg.getPayload());
+                return RocketMQLocalTransactionState.ROLLBACK;
+            }
+
+            System.out.printf("    # UNKNOW # Simulating %s related local transaction exec UNKNOWN! \n");
+            return RocketMQLocalTransactionState.UNKNOWN;
+        }
+
+        @Override
+        public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
+            String transId = (String)msg.getHeaders().get(RocketMQHeaders.TRANSACTION_ID);
+            RocketMQLocalTransactionState retState = RocketMQLocalTransactionState.COMMIT;
+            Integer status = localTrans.get(transId);
+            if (null != status) {
+                switch (status) {
+                    case 0:
+                        retState = RocketMQLocalTransactionState.UNKNOWN;
+                        break;
+                    case 1:
+                        retState = RocketMQLocalTransactionState.COMMIT;
+                        break;
+                    case 2:
+                        retState = RocketMQLocalTransactionState.ROLLBACK;
+                        break;
+                }
+            }
+            System.out.printf("------ !!! checkLocalTransaction is executed once," +
+                    " msgTransactionId=%s, TransactionState=%s status=%s %n",
+                transId, retState, status);
+            return retState;
+        }
+    }
+
+}
diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java
new file mode 100644
index 0000000..feaac0d
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.samples.springboot.domain;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+public class OrderPaidEvent implements Serializable {
+    private String orderId;
+
+    private BigDecimal paidMoney;
+
+    public OrderPaidEvent() {
+    }
+
+    public OrderPaidEvent(String orderId, BigDecimal paidMoney) {
+        this.orderId = orderId;
+        this.paidMoney = paidMoney;
+    }
+
+    public String getOrderId() {
+        return orderId;
+    }
+
+    public void setOrderId(String orderId) {
+        this.orderId = orderId;
+    }
+
+    public BigDecimal getPaidMoney() {
+        return paidMoney;
+    }
+
+    public void setPaidMoney(BigDecimal paidMoney) {
+        this.paidMoney = paidMoney;
+    }
+}
diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties
new file mode 100644
index 0000000..2187442
--- /dev/null
+++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties
@@ -0,0 +1,6 @@
+spring.rocketmq.nameServer=localhost:9876
+spring.rocketmq.producer.group=my-group1
+spring.rocketmq.topic=string-topic
+spring.rocketmq.orderTopic=order-paid-topic
+spring.rocketmq.msgExtTopic=message-ext-topic
+spring.rocketmq.transTopic=spring-transaction-topic
\ No newline at end of file
diff --git a/rocketmq-spring-boot-samples/style/copyright/Apache.xml b/rocketmq-spring-boot-samples/style/copyright/Apache.xml
new file mode 100644
index 0000000..e3e3dec
--- /dev/null
+++ b/rocketmq-spring-boot-samples/style/copyright/Apache.xml
@@ -0,0 +1,23 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<component name="CopyrightManager">
+    <copyright>
+        <option name="myName" value="Apache" />
+        <option name="notice" value="Licensed to the Apache Software Foundation (ASF) under one or more&#10;contributor license agreements.  See the NOTICE file distributed with&#10;this work for additional information regarding copyright ownership.&#10;The ASF licenses this file to You under the Apache License, Version 2.0&#10;(the &quot;License&quot;); you may not use this file except in compliance with&#10;the License.  You may obtain a copy of the License at&#10;&#10;    http://www.a [...]
+    </copyright>
+</component>
\ No newline at end of file
diff --git a/rocketmq-spring-boot-samples/style/copyright/profiles_settings.xml b/rocketmq-spring-boot-samples/style/copyright/profiles_settings.xml
new file mode 100644
index 0000000..747c7e2
--- /dev/null
+++ b/rocketmq-spring-boot-samples/style/copyright/profiles_settings.xml
@@ -0,0 +1,64 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<component name="CopyrightManager">
+    <settings default="Apache">
+        <module2copyright>
+            <element module="All" copyright="Apache"/>
+        </module2copyright>
+        <LanguageOptions name="GSP">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="HTML">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="JAVA">
+            <option name="fileTypeOverride" value="3" />
+            <option name="addBlankAfter" value="false" />
+        </LanguageOptions>
+        <LanguageOptions name="JSP">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="JSPX">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="MXML">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="Properties">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="block" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="SPI">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="block" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="XML">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="__TEMPLATE__">
+            <option name="separateBefore" value="true"/>
+            <option name="lenBefore" value="1"/>
+        </LanguageOptions>
+    </settings>
+</component>
\ No newline at end of file
diff --git a/rocketmq-spring-boot-samples/style/rmq_checkstyle.xml b/rocketmq-spring-boot-samples/style/rmq_checkstyle.xml
new file mode 100644
index 0000000..2e9658f
--- /dev/null
+++ b/rocketmq-spring-boot-samples/style/rmq_checkstyle.xml
@@ -0,0 +1,135 @@
+<?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.
+  -->
+
+<!DOCTYPE module PUBLIC
+    "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+    "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+<!--Refer http://checkstyle.sourceforge.net/reports/google-java-style.html#s2.2-file-encoding -->
+<module name="Checker">
+
+    <property name="localeLanguage" value="en"/>
+
+    <!--To configure the check to report on the first instance in each file-->
+    <module name="FileTabCharacter"/>
+
+    <!-- header -->
+    <module name="RegexpHeader">
+        <property name="header" value="/\*\nLicensed to the Apache Software Foundation*"/>
+        <property name="fileExtensions" value="java" />
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="System\.out\.println"/>
+        <property name="message" value="Prohibit invoking System.out.println in source code !"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="//FIXME"/>
+        <property name="message" value="Recommended fix FIXME task !"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="//TODO"/>
+        <property name="message" value="Recommended fix TODO task !"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="@alibaba"/>
+        <property name="message" value="Recommended remove @alibaba keyword!"/>
+    </module>
+    <module name="RegexpSingleline">
+        <property name="format" value="@taobao"/>
+        <property name="message" value="Recommended remove @taobao keyword!"/>
+    </module>
+    <module name="RegexpSingleline">
+        <property name="format" value="@author"/>
+        <property name="message" value="Recommended remove @author tag in javadoc!"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format"
+                  value=".*[\u3400-\u4DB5\u4E00-\u9FA5\u9FA6-\u9FBB\uF900-\uFA2D\uFA30-\uFA6A\uFA70-\uFAD9\uFF00-\uFFEF\u2E80-\u2EFF\u3000-\u303F\u31C0-\u31EF]+.*"/>
+        <property name="message" value="Not allow chinese character !"/>
+    </module>
+
+    <module name="FileLength">
+        <property name="max" value="3000"/>
+    </module>
+
+    <module name="TreeWalker">
+
+        <module name="UnusedImports">
+            <property name="processJavadoc" value="true"/>
+        </module>
+        <module name="RedundantImport"/>
+
+        <!--<module name="IllegalImport" />-->
+
+        <!--Checks that classes that override equals() also override hashCode()-->
+        <module name="EqualsHashCode"/>
+        <!--Checks for over-complicated boolean expressions. Currently finds code like if (topic == true), topic || true, !false, etc.-->
+        <module name="SimplifyBooleanExpression"/>
+        <module name="OneStatementPerLine"/>
+        <module name="UnnecessaryParentheses"/>
+        <!--Checks for over-complicated boolean return statements. For example the following code-->
+        <module name="SimplifyBooleanReturn"/>
+
+        <!--Check that the default is after all the cases in producerGroup switch statement-->
+        <module name="DefaultComesLast"/>
+        <!--Detects empty statements (standalone ";" semicolon)-->
+        <module name="EmptyStatement"/>
+        <!--Checks that long constants are defined with an upper ell-->
+        <module name="UpperEll"/>
+        <module name="ConstantName">
+            <property name="format" value="(^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$)|(^log$)"/>
+        </module>
+        <!--Checks that local, non-final variable names conform to producerGroup format specified by the format property-->
+        <module name="LocalVariableName"/>
+        <!--Validates identifiers for local, final variables, including catch parameters-->
+        <module name="LocalFinalVariableName"/>
+        <!--Validates identifiers for non-static fields-->
+        <module name="MemberName"/>
+        <!--Validates identifiers for class type parameters-->
+        <module name="ClassTypeParameterName">
+            <property name="format" value="^[A-Z0-9]*$"/>
+        </module>
+        <!--Validates identifiers for method type parameters-->
+        <module name="MethodTypeParameterName">
+            <property name="format" value="^[A-Z0-9]*$"/>
+        </module>
+        <module name="PackageName"/>
+        <module name="ParameterName"/>
+        <module name="StaticVariableName"/>
+        <module name="TypeName"/>
+        <!--Checks that there are no import statements that use the * notation-->
+        <module name="AvoidStarImport"/>
+
+        <!--whitespace-->
+        <module name="GenericWhitespace"/>
+        <module name="NoWhitespaceBefore"/>
+        <module name="NoWhitespaceAfter"/>
+        <module name="WhitespaceAround">
+            <property name="allowEmptyConstructors" value="true"/>
+            <property name="allowEmptyMethods" value="true"/>
+        </module>
+        <module name="Indentation"/>
+        <module name="MethodParamPad"/>
+        <module name="ParenPad"/>
+        <module name="TypecastParenPad"/>
+    </module>
+</module>
diff --git a/rocketmq-spring-boot-samples/style/rmq_codeStyle.xml b/rocketmq-spring-boot-samples/style/rmq_codeStyle.xml
new file mode 100644
index 0000000..9db075e
--- /dev/null
+++ b/rocketmq-spring-boot-samples/style/rmq_codeStyle.xml
@@ -0,0 +1,157 @@
+<!--
+  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.
+  -->
+
+<code_scheme name="rocketmq">
+    <option name="USE_SAME_INDENTS" value="true"/>
+    <option name="IGNORE_SAME_INDENTS_FOR_LANGUAGES" value="true"/>
+    <option name="OTHER_INDENT_OPTIONS">
+        <value>
+            <option name="INDENT_SIZE" value="4"/>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+            <option name="TAB_SIZE" value="4"/>
+            <option name="USE_TAB_CHARACTER" value="false"/>
+            <option name="SMART_TABS" value="false"/>
+            <option name="LABEL_INDENT_SIZE" value="0"/>
+            <option name="LABEL_INDENT_ABSOLUTE" value="false"/>
+            <option name="USE_RELATIVE_INDENTS" value="false"/>
+        </value>
+    </option>
+    <option name="PREFER_LONGER_NAMES" value="false"/>
+    <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="1000"/>
+    <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="1000"/>
+    <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
+        <value/>
+    </option>
+    <option name="IMPORT_LAYOUT_TABLE">
+        <value>
+            <package name="" withSubpackages="true" static="false"/>
+            <emptyLine/>
+            <package name="" withSubpackages="true" static="true"/>
+        </value>
+    </option>
+    <option name="JD_ALIGN_PARAM_COMMENTS" value="false"/>
+    <option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false"/>
+    <option name="JD_P_AT_EMPTY_LINES" value="false"/>
+    <option name="JD_KEEP_INVALID_TAGS" value="false"/>
+    <option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true"/>
+    <option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
+    <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+    <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+    <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+    <option name="ELSE_ON_NEW_LINE" value="true"/>
+    <option name="WHILE_ON_NEW_LINE" value="true"/>
+    <option name="CATCH_ON_NEW_LINE" value="true"/>
+    <option name="FINALLY_ON_NEW_LINE" value="true"/>
+    <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+    <option name="ALIGN_MULTILINE_FOR" value="false"/>
+    <option name="SPACE_AFTER_TYPE_CAST" value="false"/>
+    <option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true"/>
+    <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+    <option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true"/>
+    <option name="LABELED_STATEMENT_WRAP" value="1"/>
+    <option name="WRAP_COMMENTS" value="true"/>
+    <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+    <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+    <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+    <JavaCodeStyleSettings>
+        <option name="CLASS_NAMES_IN_JAVADOC" value="3"/>
+    </JavaCodeStyleSettings>
+    <XML>
+        <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true"/>
+    </XML>
+    <ADDITIONAL_INDENT_OPTIONS fileType="haml">
+        <option name="INDENT_SIZE" value="2"/>
+    </ADDITIONAL_INDENT_OPTIONS>
+    <codeStyleSettings language="Groovy">
+        <option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
+        <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="ELSE_ON_NEW_LINE" value="true"/>
+        <option name="CATCH_ON_NEW_LINE" value="true"/>
+        <option name="FINALLY_ON_NEW_LINE" value="true"/>
+        <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+        <option name="ALIGN_MULTILINE_FOR" value="false"/>
+        <option name="SPACE_AFTER_TYPE_CAST" value="false"/>
+        <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+        <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+        <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+        <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+        <indentOptions>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+    <codeStyleSettings language="HOCON">
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+    </codeStyleSettings>
+    <codeStyleSettings language="JAVA">
+        <option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
+        <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="ELSE_ON_NEW_LINE" value="true"/>
+        <option name="WHILE_ON_NEW_LINE" value="true"/>
+        <option name="CATCH_ON_NEW_LINE" value="true"/>
+        <option name="FINALLY_ON_NEW_LINE" value="true"/>
+        <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+        <option name="ALIGN_MULTILINE_FOR" value="false"/>
+        <option name="SPACE_AFTER_TYPE_CAST" value="false"/>
+        <option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true"/>
+        <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+        <option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true"/>
+        <option name="LABELED_STATEMENT_WRAP" value="1"/>
+        <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+        <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+        <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+        <indentOptions>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+    <codeStyleSettings language="JSON">
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+    </codeStyleSettings>
+    <codeStyleSettings language="Scala">
+        <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="ELSE_ON_NEW_LINE" value="true"/>
+        <option name="WHILE_ON_NEW_LINE" value="true"/>
+        <option name="CATCH_ON_NEW_LINE" value="true"/>
+        <option name="FINALLY_ON_NEW_LINE" value="true"/>
+        <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+        <option name="ALIGN_MULTILINE_FOR" value="false"/>
+        <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+        <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+        <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+        <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+        <indentOptions>
+            <option name="INDENT_SIZE" value="4"/>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+            <option name="TAB_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+    <codeStyleSettings language="XML">
+        <indentOptions>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+</code_scheme>
\ No newline at end of file
diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml
new file mode 100644
index 0000000..cd88b71
--- /dev/null
+++ b/rocketmq-spring-boot-starter/pom.xml
@@ -0,0 +1,51 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.rocketmq</groupId>
+        <artifactId>rocketmq-spring-boot-parent</artifactId>
+        <version>2.0.0</version>
+        <relativePath>../rocketmq-spring-boot-parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>rocketmq-spring-boot-starter</artifactId>
+    <packaging>jar</packaging>
+
+    <name>RocketMQ Spring Boot Starter</name>
+    <description>SRocketMQ Spring Boot Starter</description>
+    <url>https://github.com/apache/rocketmq-spring</url>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.rocketmq</groupId>
+            <artifactId>rocketmq-spring-boot</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/rocketmq-spring-boot/README.md b/rocketmq-spring-boot/README.md
new file mode 100644
index 0000000..a4d3022
--- /dev/null
+++ b/rocketmq-spring-boot/README.md
@@ -0,0 +1,7 @@
+# RocketMQ Spring Boot Support
+This project provides auto-configuration for the following RocketMQ client:
+
+- [Produce and Consume Spring Message](../rocketmq-spring-boot-starter)
+- [Send (halp) Message in Transaction](../rocketmq-spring-boot-starter)
+
+For details, please see sample code in the [rocketmq-spring-boot-samples](../rocketmq-spring-boot-samples)
\ No newline at end of file
diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml
new file mode 100644
index 0000000..94e528c
--- /dev/null
+++ b/rocketmq-spring-boot/pom.xml
@@ -0,0 +1,104 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.rocketmq</groupId>
+        <artifactId>rocketmq-spring-boot-parent</artifactId>
+        <version>2.0.0</version>
+        <relativePath>../rocketmq-spring-boot-parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>rocketmq-spring-boot</artifactId>
+    <packaging>jar</packaging>
+
+    <name>RocketMQ Spring Boot AutoConfigure</name>
+    <description>SRocketMQ Spring Boot AutoConfigure</description>
+    <url>https://github.com/apache/rocketmq-spring</url>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-autoconfigure-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.rocketmq</groupId>
+            <artifactId>rocketmq-client</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-messaging</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-aop</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ConsumeMode.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ConsumeMode.java
new file mode 100644
index 0000000..1b9f35a
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ConsumeMode.java
@@ -0,0 +1,30 @@
+/*
+ * 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.rocketmq.spring.annotation;
+
+public enum ConsumeMode {
+    /**
+     * Receive asynchronously delivered messages concurrently
+     */
+    CONCURRENTLY,
+
+    /**
+     * Receive asynchronously delivered messages orderly. one queue, one thread
+     */
+    ORDERLY
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/MessageModel.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/MessageModel.java
new file mode 100644
index 0000000..9bdaa64
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/MessageModel.java
@@ -0,0 +1,33 @@
+/*
+ * 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.rocketmq.spring.annotation;
+
+public enum MessageModel {
+    BROADCASTING("BROADCASTING"),
+    CLUSTERING("CLUSTERING");
+
+    private String modeCN;
+
+    MessageModel(String modeCN) {
+        this.modeCN = modeCN;
+    }
+
+    public String getModeCN() {
+        return this.modeCN;
+    }
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQMessageListener.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQMessageListener.java
new file mode 100644
index 0000000..762ea82
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQMessageListener.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.rocketmq.spring.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RocketMQMessageListener {
+
+    /**
+     * Consumers of the same role is required to have exactly same subscriptions and consumerGroup to correctly achieve
+     * load balance. It's required and needs to be globally unique.
+     *
+     *
+     * See <a href="http://rocketmq.apache.org/docs/core-concept/">here</a> for further discussion.
+     */
+    String consumerGroup();
+
+    /**
+     * Topic name.
+     */
+    String topic();
+
+    /**
+     * Control how to selector message.
+     *
+     * @see SelectorType
+     */
+    SelectorType selectorType() default SelectorType.TAG;
+
+    /**
+     * Control which message can be select. Grammar please see {@link SelectorType#TAG} and {@link SelectorType#SQL92}
+     */
+    String selectorExpression() default "*";
+
+    /**
+     * Control consume mode, you can choice receive message concurrently or orderly.
+     */
+    ConsumeMode consumeMode() default ConsumeMode.CONCURRENTLY;
+
+    /**
+     * Control message mode, if you want all subscribers receive message all message, broadcasting is a good choice.
+     */
+    MessageModel messageModel() default MessageModel.CLUSTERING;
+
+    /**
+     * Max consumer thread number.
+     */
+    int consumeThreadMax() default 64;
+
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQTransactionListener.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQTransactionListener.java
new file mode 100644
index 0000000..b355641
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQTransactionListener.java
@@ -0,0 +1,69 @@
+/*
+ * 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.rocketmq.spring.annotation;
+
+import org.apache.rocketmq.spring.config.RocketMQConfigUtils;
+import org.springframework.stereotype.Component;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation is used over a class which implements interface
+ * org.apache.rocketmq.client.producer.TransactionListener. The class implements
+ * two methods for process callback events after the txProducer sends a transactional message.
+ * <p>Note: The annotation is used only on RocketMQ client producer side, it can not be used
+ * on consumer side.
+ */
+@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Component
+public @interface RocketMQTransactionListener {
+
+    /**
+     * Declare the txProducerGroup that is used to relate callback event to the listener, rocketMQTemplate must send a
+     * transactional message with the declared txProducerGroup.
+     * <p>
+     * <p>It is suggested to use the default txProducerGroup if your system only needs to define a TransactionListener class.
+     */
+    String txProducerGroup() default RocketMQConfigUtils.ROCKETMQ_TRANSACTION_DEFAULT_GLOBAL_NAME;
+
+    /**
+     * Set ExecutorService params -- corePoolSize
+     */
+    int corePoolSize() default 1;
+
+    /**
+     * Set ExecutorService params -- maximumPoolSize
+     */
+    int maximumPoolSize() default 1;
+
+    /**
+     * Set ExecutorService params -- keepAliveTime
+     */
+    long keepAliveTime() default 1000 * 60; //60ms
+
+    /**
+     * Set ExecutorService params -- blockingQueueSize
+     */
+    int blockingQueueSize() default 2000;
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/SelectorType.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/SelectorType.java
new file mode 100644
index 0000000..97e8b7e
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/SelectorType.java
@@ -0,0 +1,33 @@
+/*
+ * 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.rocketmq.spring.annotation;
+
+import org.apache.rocketmq.common.filter.ExpressionType;
+
+public enum SelectorType {
+
+    /**
+     * @see ExpressionType#TAG
+     */
+    TAG,
+
+    /**
+     * @see ExpressionType#SQL92
+     */
+    SQL92
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
new file mode 100644
index 0000000..e1fab88
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
@@ -0,0 +1,133 @@
+/*
+ * 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.rocketmq.spring.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.rocketmq.spring.annotation.ConsumeMode;
+import org.apache.rocketmq.spring.annotation.MessageModel;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.SmartInitializingSingleton;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.support.BeanDefinitionValidationException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.core.env.StandardEnvironment;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicLong;
+
+
+public class ListenerContainerConfiguration implements ApplicationContextAware, SmartInitializingSingleton {
+    private final static Logger log = LoggerFactory.getLogger(RocketMQAutoConfiguration.class);
+
+    private ConfigurableApplicationContext applicationContext;
+
+    private AtomicLong counter = new AtomicLong(0);
+
+    private StandardEnvironment environment;
+
+    private RocketMQProperties rocketMQProperties;
+
+    private ObjectMapper objectMapper;
+
+    public ListenerContainerConfiguration() {
+    }
+
+    @Autowired
+    public ListenerContainerConfiguration(
+        @Qualifier("rocketMQMessageObjectMapper") ObjectMapper objectMapper,
+        StandardEnvironment environment,
+        RocketMQProperties rocketMQProperties) {
+        this.objectMapper = objectMapper;
+        this.environment = environment;
+        this.rocketMQProperties = rocketMQProperties;
+    }
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        this.applicationContext = (ConfigurableApplicationContext) applicationContext;
+    }
+
+    @Override
+    public void afterSingletonsInstantiated() {
+        Map<String, Object> beans = this.applicationContext.getBeansWithAnnotation(RocketMQMessageListener.class);
+
+        if (Objects.nonNull(beans)) {
+            beans.forEach(this::registerContainer);
+        }
+    }
+
+    private void registerContainer(String beanName, Object bean) {
+        Class<?> clazz = AopUtils.getTargetClass(bean);
+
+        if (!RocketMQListener.class.isAssignableFrom(bean.getClass())) {
+            throw new IllegalStateException(clazz + " is not instance of " + RocketMQListener.class.getName());
+        }
+
+        RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class);
+        validate(annotation);
+
+        String containerBeanName = String.format("%s_%s", DefaultRocketMQListenerContainer.class.getName(),
+            counter.incrementAndGet());
+        GenericApplicationContext genericApplicationContext = (GenericApplicationContext) applicationContext;
+
+        genericApplicationContext.registerBean(containerBeanName, DefaultRocketMQListenerContainer.class,
+            () -> createRocketMQListenerContainer(bean, annotation));
+        DefaultRocketMQListenerContainer container = genericApplicationContext.getBean(containerBeanName,
+            DefaultRocketMQListenerContainer.class);
+        if (!container.isRunning()) {
+            try {
+                container.start();
+            } catch (Exception e) {
+                log.error("Started container failed. {}", container, e);
+                throw new RuntimeException(e);
+            }
+        }
+
+        log.info("Register the listener to container, listenerBeanName:{}, containerBeanName:{}", beanName, containerBeanName);
+    }
+
+    private DefaultRocketMQListenerContainer createRocketMQListenerContainer(Object bean, RocketMQMessageListener annotation) {
+        DefaultRocketMQListenerContainer container = new DefaultRocketMQListenerContainer();
+
+        container.setNameServer(rocketMQProperties.getNameServer());
+        container.setTopic(environment.resolvePlaceholders(annotation.topic()));
+        container.setConsumerGroup(environment.resolvePlaceholders(annotation.consumerGroup()));
+        container.setRocketMQMessageListener(annotation);
+        container.setRocketMQListener((RocketMQListener) bean);
+        container.setObjectMapper(objectMapper);
+
+        return container;
+    }
+
+    private void validate(RocketMQMessageListener annotation) {
+        if (annotation.consumeMode() == ConsumeMode.ORDERLY &&
+            annotation.messageModel() == MessageModel.BROADCASTING)
+            throw new BeanDefinitionValidationException("Bad annotation definition in @RocketMQMessageListener, messageModel BROADCASTING does not support ORDERLY message!");
+    }
+}
\ No newline at end of file
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
new file mode 100644
index 0000000..c22c6ee
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
@@ -0,0 +1,104 @@
+/*
+ * 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.rocketmq.spring.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.rocketmq.client.producer.DefaultMQProducer;
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.Role;
+import org.springframework.util.Assert;
+
+import java.util.Objects;
+
+@Configuration
+@EnableConfigurationProperties(RocketMQProperties.class)
+@ConditionalOnProperty(prefix = "spring.rocketmq", value = "nameServer")
+@Import(ListenerContainerConfiguration.class)
+public class RocketMQAutoConfiguration {
+
+    @Bean
+    @ConditionalOnMissingBean(DefaultMQProducer.class)
+    @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"nameServer", "producer.group"})
+    public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties) {
+        RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer();
+        String nameServer = rocketMQProperties.getNameServer();
+        String groupName = producerConfig.getGroup();
+        Assert.hasText(nameServer, "[spring.rocketmq.nameServer] must not be null");
+        Assert.hasText(groupName, "[spring.rocketmq.producer.group] must not be null");
+
+        DefaultMQProducer producer = new DefaultMQProducer(groupName);
+        producer.setNamesrvAddr(nameServer);
+        producer.setSendMsgTimeout(producerConfig.getSendMessageTimeout());
+        producer.setRetryTimesWhenSendFailed(producerConfig.getRetryTimesWhenSendFailed());
+        producer.setRetryTimesWhenSendAsyncFailed(producerConfig.getRetryTimesWhenSendAsyncFailed());
+        producer.setMaxMessageSize(producerConfig.getMaxMessageSize());
+        producer.setCompressMsgBodyOverHowmuch(producerConfig.getCompressMessageBodyOverHowmuch());
+        producer.setRetryAnotherBrokerWhenNotStoreOK(producerConfig.isRetryAnotherBrokerWhenNotStoreOk());
+
+        return producer;
+    }
+
+    @Bean
+    @ConditionalOnClass(name = "com.fasterxml.jackson.databind.ObjectMapper")
+    @ConditionalOnMissingBean(ObjectMapper.class)
+    public ObjectMapper rocketMQMessageObjectMapper() {
+        return new ObjectMapper();
+    }
+
+    @Bean(destroyMethod = "destroy")
+    @ConditionalOnBean(DefaultMQProducer.class)
+    @ConditionalOnMissingBean(RocketMQTemplate.class)
+    public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer,
+        @Autowired(required = false)
+        @Qualifier("rocketMQMessageObjectMapper")
+            ObjectMapper objectMapper) {
+        RocketMQTemplate rocketMQTemplate = new RocketMQTemplate();
+        rocketMQTemplate.setProducer(mqProducer);
+        if (Objects.nonNull(objectMapper)) {
+            rocketMQTemplate.setObjectMapper(objectMapper);
+        } else {
+            throw new IllegalStateException("Can not inject null objectMapper into RocketMQTemplate!");
+        }
+        return rocketMQTemplate;
+    }
+
+    @Bean
+    @ConditionalOnBean(RocketMQTemplate.class)
+    @ConditionalOnMissingBean(TransactionHandlerRegistry.class)
+    public TransactionHandlerRegistry transactionHandlerRegistry(RocketMQTemplate template) {
+        return new TransactionHandlerRegistry(template);
+    }
+
+    @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME)
+    @ConditionalOnBean(TransactionHandlerRegistry.class)
+    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
+    public RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor(TransactionHandlerRegistry transactionHandlerRegistry) {
+        return new RocketMQTransactionAnnotationProcessor(transactionHandlerRegistry);
+    }
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQConfigUtils.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQConfigUtils.java
new file mode 100644
index 0000000..a9c9f80
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQConfigUtils.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.spring.config;
+
+public class RocketMQConfigUtils {
+    /**
+     * The bean name of the internally managed RocketMQ transaction annotation processor.
+     */
+    public static final String ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME =
+        "org.springframework.rocketmq.spring.starter.internalRocketMQTransAnnotationProcessor";
+
+    public static final String ROCKETMQ_TRANSACTION_DEFAULT_GLOBAL_NAME =
+        "rocketmq_transaction_default_global_name";
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
new file mode 100644
index 0000000..8590e05
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
@@ -0,0 +1,144 @@
+/*
+ * 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.rocketmq.spring.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@SuppressWarnings("WeakerAccess")
+@ConfigurationProperties(prefix = "spring.rocketmq")
+public class RocketMQProperties {
+
+    /**
+     * The name server for rocketMQ, formats: `host:port;host:port`.
+     */
+    private String nameServer;
+
+    private Producer producer;
+
+    public String getNameServer() {
+        return nameServer;
+    }
+
+    public void setNameServer(String nameServer) {
+        this.nameServer = nameServer;
+    }
+
+    public RocketMQProperties.Producer getProducer() {
+        return producer;
+    }
+
+    public void setProducer(RocketMQProperties.Producer producer) {
+        this.producer = producer;
+    }
+
+    public static class Producer {
+
+        /**
+         * Name of producer.
+         */
+        private String group;
+
+        /**
+         * Millis of send message timeout.
+         */
+        private int sendMessageTimeout = 3000;
+
+        /**
+         * Compress message body threshold, namely, message body larger than 4k will be compressed on default.
+         */
+        private int compressMessageBodyOverHowmuch = 1024 * 4;
+
+        /**
+         * Maximum number of retry to perform internally before claiming sending failure in synchronous mode.
+         * This may potentially cause message duplication which is up to application developers to resolve.
+         */
+        private int retryTimesWhenSendFailed = 2;
+
+        /**
+         * <p> Maximum number of retry to perform internally before claiming sending failure in asynchronous mode. </p>
+         * This may potentially cause message duplication which is up to application developers to resolve.
+         */
+        private int retryTimesWhenSendAsyncFailed = 2;
+
+        /**
+         * Indicate whether to retry another broker on sending failure internally.
+         */
+        private boolean retryAnotherBrokerWhenNotStoreOk = false;
+
+        /**
+         * Maximum allowed message size in bytes.
+         */
+        private int maxMessageSize = 1024 * 1024 * 4;
+
+        public String getGroup() {
+            return group;
+        }
+
+        public void setGroup(String group) {
+            this.group = group;
+        }
+
+        public int getSendMessageTimeout() {
+            return sendMessageTimeout;
+        }
+
+        public void setSendMessageTimeout(int sendMessageTimeout) {
+            this.sendMessageTimeout = sendMessageTimeout;
+        }
+
+        public int getCompressMessageBodyOverHowmuch() {
+            return compressMessageBodyOverHowmuch;
+        }
+
+        public void setCompressMessageBodyOverHowmuch(int compressMessageBodyOverHowmuch) {
+            this.compressMessageBodyOverHowmuch = compressMessageBodyOverHowmuch;
+        }
+
+        public int getRetryTimesWhenSendFailed() {
+            return retryTimesWhenSendFailed;
+        }
+
+        public void setRetryTimesWhenSendFailed(int retryTimesWhenSendFailed) {
+            this.retryTimesWhenSendFailed = retryTimesWhenSendFailed;
+        }
+
+        public int getRetryTimesWhenSendAsyncFailed() {
+            return retryTimesWhenSendAsyncFailed;
+        }
+
+        public void setRetryTimesWhenSendAsyncFailed(int retryTimesWhenSendAsyncFailed) {
+            this.retryTimesWhenSendAsyncFailed = retryTimesWhenSendAsyncFailed;
+        }
+
+        public boolean isRetryAnotherBrokerWhenNotStoreOk() {
+            return retryAnotherBrokerWhenNotStoreOk;
+        }
+
+        public void setRetryAnotherBrokerWhenNotStoreOk(boolean retryAnotherBrokerWhenNotStoreOk) {
+            this.retryAnotherBrokerWhenNotStoreOk = retryAnotherBrokerWhenNotStoreOk;
+        }
+
+        public int getMaxMessageSize() {
+            return maxMessageSize;
+        }
+
+        public void setMaxMessageSize(int maxMessageSize) {
+            this.maxMessageSize = maxMessageSize;
+        }
+    }
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQTransactionAnnotationProcessor.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQTransactionAnnotationProcessor.java
new file mode 100644
index 0000000..cd78fdb
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQTransactionAnnotationProcessor.java
@@ -0,0 +1,110 @@
+/*
+ * 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.rocketmq.spring.config;
+
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
+import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.AnnotationUtils;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RocketMQTransactionAnnotationProcessor
+    implements BeanPostProcessor, Ordered, BeanFactoryAware {
+    private final static Logger log = LoggerFactory.getLogger(RocketMQTransactionAnnotationProcessor.class);
+
+    private BeanFactory beanFactory;
+    private final Set<Class<?>> nonProcessedClasses =
+        Collections.newSetFromMap(new ConcurrentHashMap<Class<?>, Boolean>(64));
+
+    private TransactionHandlerRegistry transactionHandlerRegistry;
+
+    public RocketMQTransactionAnnotationProcessor(TransactionHandlerRegistry transactionHandlerRegistry) {
+        this.transactionHandlerRegistry = transactionHandlerRegistry;
+    }
+
+    @Override
+    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+        this.beanFactory = beanFactory;
+    }
+
+    @Override
+    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+        return bean;
+    }
+
+    @Override
+    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+        if (!this.nonProcessedClasses.contains(bean.getClass())) {
+            Class<?> targetClass = AopUtils.getTargetClass(bean);
+            RocketMQTransactionListener listener = AnnotationUtils.findAnnotation(targetClass, RocketMQTransactionListener.class);
+            this.nonProcessedClasses.add(bean.getClass());
+            if (listener == null) { // for quick search
+                log.trace("No @RocketMQTransactionListener annotations found on bean type: {}", bean.getClass());
+            } else {
+                try {
+                    processTransactionListenerAnnotation(listener, bean);
+                } catch (MQClientException e) {
+                    log.error("Failed to process annotation " + listener, e);
+                    throw new BeanCreationException("Failed to process annotation " + listener, e);
+                }
+            }
+        }
+
+        return bean;
+    }
+
+    private void processTransactionListenerAnnotation(RocketMQTransactionListener listener, Object bean)
+        throws MQClientException {
+        if (transactionHandlerRegistry == null) {
+            throw new MQClientException("Bad usage of @RocketMQTransactionListener, " +
+                "the class must work with RocketMQTemplate", null);
+        }
+        if (!RocketMQLocalTransactionListener.class.isAssignableFrom(bean.getClass())) {
+            throw new MQClientException("Bad usage of @RocketMQTransactionListener, " +
+                "the class must implement interface RocketMQLocalTransactionListener",
+                null);
+        }
+        TransactionHandler transactionHandler = new TransactionHandler();
+        transactionHandler.setBeanFactory(this.beanFactory);
+        transactionHandler.setName(listener.txProducerGroup());
+        transactionHandler.setBeanName(bean.getClass().getName());
+        transactionHandler.setListener((RocketMQLocalTransactionListener) bean);
+        transactionHandler.setCheckExecutor(listener.corePoolSize(), listener.maximumPoolSize(),
+                listener.keepAliveTime(), listener.blockingQueueSize());
+
+        transactionHandlerRegistry.registerTransactionHandler(transactionHandler);
+    }
+
+    @Override
+    public int getOrder() {
+        return LOWEST_PRECEDENCE;
+    }
+
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandler.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandler.java
new file mode 100644
index 0000000..f6f6955
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandler.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.spring.config;
+
+import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
+import org.springframework.beans.factory.BeanFactory;
+
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+class TransactionHandler {
+    private String name;
+    private String beanName;
+    private RocketMQLocalTransactionListener bean;
+    private BeanFactory beanFactory;
+    private ThreadPoolExecutor checkExecutor;
+
+    public String getBeanName() {
+        return beanName;
+    }
+
+    public void setBeanName(String beanName) {
+        this.beanName = beanName;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public BeanFactory getBeanFactory() {
+        return beanFactory;
+    }
+
+    public void setBeanFactory(BeanFactory beanFactory) {
+        this.beanFactory = beanFactory;
+    }
+
+    public void setListener(RocketMQLocalTransactionListener listener) {
+        this.bean = listener;
+    }
+
+    public RocketMQLocalTransactionListener getListener() {
+        return this.bean;
+    }
+
+    public void setCheckExecutor(int corePoolSize, int maxPoolSize, long keepAliveTime, int blockingQueueSize) {
+        this.checkExecutor = new ThreadPoolExecutor(corePoolSize, maxPoolSize,
+            keepAliveTime, TimeUnit.MILLISECONDS,
+            new LinkedBlockingDeque<>(blockingQueueSize));
+    }
+
+    public ThreadPoolExecutor getCheckExecutor() {
+        return checkExecutor;
+    }
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java
new file mode 100644
index 0000000..73a1244
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.spring.config;
+
+import io.netty.util.internal.ConcurrentSet;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.springframework.beans.factory.DisposableBean;
+
+import java.util.Set;
+
+public class TransactionHandlerRegistry implements DisposableBean {
+    private RocketMQTemplate rocketMQTemplate;
+
+    private final Set<String> listenerContainers = new ConcurrentSet<>();
+
+    public TransactionHandlerRegistry(RocketMQTemplate template) {
+        this.rocketMQTemplate = template;
+    }
+
+    @Override
+    public void destroy() throws Exception {
+        listenerContainers.clear();
+    }
+
+    public void registerTransactionHandler(TransactionHandler handler) throws MQClientException {
+        if (listenerContainers.contains(handler.getName()))
+            throw new MQClientException(-1,
+                String.format("The transaction name [%s] has been defined in TransactionListener [%s]", handler.getName(),
+                    handler.getBeanName()));
+        listenerContainers.add(handler.getName());
+
+        rocketMQTemplate.createAndStartTransactionMQProducer(handler.getName(), handler.getListener(), handler.getCheckExecutor());
+    }
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQListener.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQListener.java
new file mode 100644
index 0000000..bd6ceeb
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQListener.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.spring.core;
+
+public interface RocketMQListener<T> {
+    void onMessage(T message);
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionListener.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionListener.java
new file mode 100644
index 0000000..890aecc
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionListener.java
@@ -0,0 +1,25 @@
+/*
+ * 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.rocketmq.spring.core;
+
+import org.springframework.messaging.Message;
+
+public interface RocketMQLocalTransactionListener {
+    RocketMQLocalTransactionState executeLocalTransaction(final Message msg, final Object arg);
+
+    RocketMQLocalTransactionState checkLocalTransaction(final Message msg);
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionState.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionState.java
new file mode 100644
index 0000000..91f0bec
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionState.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.spring.core;
+
+public enum RocketMQLocalTransactionState {
+    COMMIT,
+    ROLLBACK,
+    UNKNOWN
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQPushConsumerLifecycleListener.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQPushConsumerLifecycleListener.java
new file mode 100644
index 0000000..3be8cdc
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQPushConsumerLifecycleListener.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.spring.core;
+
+import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
+import org.apache.rocketmq.spring.support.RocketMQConsumerLifecycleListener;
+
+public interface RocketMQPushConsumerLifecycleListener extends RocketMQConsumerLifecycleListener<DefaultMQPushConsumer> {
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQTemplate.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQTemplate.java
new file mode 100644
index 0000000..f8c7c64
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQTemplate.java
@@ -0,0 +1,609 @@
+/*
+ * 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.rocketmq.spring.core;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.producer.DefaultMQProducer;
+import org.apache.rocketmq.client.producer.MessageQueueSelector;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.client.producer.TransactionMQProducer;
+import org.apache.rocketmq.client.producer.TransactionSendResult;
+import org.apache.rocketmq.client.producer.selector.SelectMessageQueueByHash;
+import org.apache.rocketmq.spring.config.RocketMQConfigUtils;
+import org.apache.rocketmq.spring.support.RocketMQUtil;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageHeaders;
+import org.springframework.messaging.MessagingException;
+import org.springframework.messaging.core.AbstractMessageSendingTemplate;
+import org.springframework.messaging.core.MessagePostProcessor;
+import org.springframework.messaging.support.MessageBuilder;
+import org.springframework.util.Assert;
+import org.springframework.util.MimeTypeUtils;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings({"WeakerAccess", "unused"})
+public class RocketMQTemplate extends AbstractMessageSendingTemplate<String> implements InitializingBean, DisposableBean {
+    private static final  Logger log = LoggerFactory.getLogger(RocketMQTemplate.class);
+
+    private DefaultMQProducer producer;
+
+    private ObjectMapper objectMapper;
+
+    private String charset = "UTF-8";
+
+    private MessageQueueSelector messageQueueSelector = new SelectMessageQueueByHash();
+
+    private final Map<String, TransactionMQProducer> cache = new ConcurrentHashMap<>(); //only put TransactionMQProducer by now!!!
+
+    public DefaultMQProducer getProducer() {
+        return producer;
+    }
+
+    public void setProducer(DefaultMQProducer producer) {
+        this.producer = producer;
+    }
+
+    public ObjectMapper getObjectMapper() {
+        return objectMapper;
+    }
+
+    public void setObjectMapper(ObjectMapper objectMapper) {
+        this.objectMapper = objectMapper;
+    }
+
+    public String getCharset() {
+        return charset;
+    }
+
+    public void setCharset(String charset) {
+        this.charset = charset;
+    }
+
+    public MessageQueueSelector getMessageQueueSelector() {
+        return messageQueueSelector;
+    }
+
+    public void setMessageQueueSelector(MessageQueueSelector messageQueueSelector) {
+        this.messageQueueSelector = messageQueueSelector;
+    }
+
+    /**
+     * <p> Send message in synchronous mode. This method returns only when the sending procedure totally completes.
+     * Reliable synchronous transmission is used in extensive scenes, such as important notification messages, SMS
+     * notification, SMS marketing system, etc.. </p>
+     * <p>
+     * <strong>Warn:</strong> this method has internal retry-mechanism, that is, internal implementation will retry
+     * {@link DefaultMQProducer#getRetryTimesWhenSendFailed} times before claiming failure. As a result, multiple
+     * messages may potentially delivered to broker(s). It's up to the application developers to resolve potential
+     * duplication issue.
+     *
+     * @param destination formats: `topicName:tags`
+     * @param message     {@link org.springframework.messaging.Message}
+     * @return {@link SendResult}
+     */
+    public SendResult syncSend(String destination, Message<?> message) {
+        return syncSend(destination, message, producer.getSendMsgTimeout());
+    }
+
+    /**
+     * Same to {@link #syncSend(String, Message)} with send timeout specified in addition.
+     *
+     * @param destination formats: `topicName:tags`
+     * @param message     {@link org.springframework.messaging.Message}
+     * @param timeout     send timeout with millis
+     * @return {@link SendResult}
+     */
+    public SendResult syncSend(String destination, Message<?> message, long timeout) {
+        return syncSend(destination, message, timeout, 0);
+    }
+
+    /**
+     * Same to {@link #syncSend(String, Message)} with send timeout specified in addition.
+     *
+     * @param destination formats: `topicName:tags`
+     * @param message     {@link org.springframework.messaging.Message}
+     * @param timeout     send timeout with millis
+     * @param delayLevel  level for the delay message
+     * @return {@link SendResult}
+     */
+    public SendResult syncSend(String destination, Message<?> message, long timeout, int delayLevel) {
+        if (Objects.isNull(message) || Objects.isNull(message.getPayload())) {
+            log.error("syncSend failed. destination:{}, message is null ", destination);
+            throw new IllegalArgumentException("`message` and `message.payload` cannot be null");
+        }
+
+        try {
+            long now = System.currentTimeMillis();
+            org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper,
+                charset, destination, message);
+            if (delayLevel > 0) {
+                rocketMsg.setDelayTimeLevel(delayLevel);
+            }
+            SendResult sendResult = producer.send(rocketMsg, timeout);
+            long costTime = System.currentTimeMillis() - now;
+            log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId());
+            return sendResult;
+        } catch (Exception e) {
+            log.error("syncSend failed. destination:{}, message:{} ", destination, message);
+            throw new MessagingException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Same to {@link #syncSend(String, Message)}.
+     *
+     * @param destination formats: `topicName:tags`
+     * @param payload     the Object to use as payload
+     * @return {@link SendResult}
+     */
+    public SendResult syncSend(String destination, Object payload) {
+        return syncSend(destination, payload, producer.getSendMsgTimeout());
+    }
+
+    /**
+     * Same to {@link #syncSend(String, Object)} with send timeout specified in addition.
+     *
+     * @param destination formats: `topicName:tags`
+     * @param payload     the Object to use as payload
+     * @param timeout     send timeout with millis
+     * @return {@link SendResult}
+     */
+    public SendResult syncSend(String destination, Object payload, long timeout) {
+        Message<?> message = this.doConvert(payload, null, null);
+        return syncSend(destination, message, timeout);
+    }
+
+    /**
+     * Same to {@link #syncSend(String, Message)} with send orderly with hashKey by specified.
+     *
+     * @param destination formats: `topicName:tags`
+     * @param message     {@link org.springframework.messaging.Message}
+     * @param hashKey     use this key to select queue. for example: orderId, productId ...
+     * @return {@link SendResult}
+     */
+    public SendResult syncSendOrderly(String destination, Message<?> message, String hashKey) {
+        return syncSendOrderly(destination, message, hashKey, producer.getSendMsgTimeout());
+    }
+
+    /**
+     * Same to {@link #syncSendOrderly(String, Message, String)} with send timeout specified in addition.
+     *
+     * @param destination formats: `topicName:tags`
+     * @param message     {@link org.springframework.messaging.Message}
+     * @param hashKey     use this key to select queue. for example: orderId, productId ...
+     * @param timeout     send timeout with millis
+     * @return {@link SendResult}
+     */
+    public SendResult syncSendOrderly(String destination, Message<?> message, String hashKey, long timeout) {
+        if (Objects.isNull(message) || Objects.isNull(message.getPayload())) {
+            log.error("syncSendOrderly failed. destination:{}, message is null ", destination);
+            throw new IllegalArgumentException("`message` and `message.payload` cannot be null");
+        }
+
+        try {
+            long now = System.currentTimeMillis();
+            org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper,
+                charset, destination, message);
+            SendResult sendResult = producer.send(rocketMsg, messageQueueSelector, hashKey, timeout);
+            long costTime = System.currentTimeMillis() - now;
+            log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId());
+            return sendResult;
+        } catch (Exception e) {
+            log.error("syncSendOrderly failed. destination:{}, message:{} ", destination, message);
+            throw new MessagingException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Same to {@link #syncSend(String, Object)} with send orderly with hashKey by specified.
+     *
+     * @param destination formats: `topicName:tags`
+     * @param payload     the Object to use as payload
+     * @param hashKey     use this key to select queue. for example: orderId, productId ...
+     * @return {@link SendResult}
+     */
+    public SendResult syncSendOrderly(String destination, Object payload, String hashKey) {
+        return syncSendOrderly(destination, payload, hashKey, producer.getSendMsgTimeout());
+    }
+
+    /**
+     * Same to {@link #syncSendOrderly(String, Object, String)} with send timeout specified in addition.
+     *
+     * @param destination formats: `topicName:tags`
+     * @param payload     the Object to use as payload
+     * @param hashKey     use this key to select queue. for example: orderId, productId ...
+     * @param timeout     send timeout with millis
+     * @return {@link SendResult}
+     */
+    public SendResult syncSendOrderly(String destination, Object payload, String hashKey, long timeout) {
+        Message<?> message = this.doConvert(payload, null, null);
+        return syncSendOrderly(destination, message, hashKey, producer.getSendMsgTimeout());
+    }
+
+    /**
+     * Same to {@link #asyncSend(String, Message, SendCallback)} with send timeout specified in addition.
+     *
+     * @param destination  formats: `topicName:tags`
+     * @param message      {@link org.springframework.messaging.Message}
+     * @param sendCallback {@link SendCallback}
+     * @param timeout      send timeout with millis
+     */
+    public void asyncSend(String destination, Message<?> message, SendCallback sendCallback, long timeout) {
+        if (Objects.isNull(message) || Objects.isNull(message.getPayload())) {
+            log.error("asyncSend failed. destination:{}, message is null ", destination);
+            throw new IllegalArgumentException("`message` and `message.payload` cannot be null");
+        }
+
+        try {
+            org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper,
+                charset, destination, message);
+            producer.send(rocketMsg, sendCallback, timeout);
+        } catch (Exception e) {
+            log.info("asyncSend failed. destination:{}, message:{} ", destination, message);
+            throw new MessagingException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * <p> Send message to broker asynchronously. asynchronous transmission is generally used in response time sensitive
+     * business scenarios. </p>
+     * <p>
+     * This method returns immediately. On sending completion, <code>sendCallback</code> will be executed.
+     * <p>
+     * Similar to {@link #syncSend(String, Object)}, internal implementation would potentially retry up to {@link
+     * DefaultMQProducer#getRetryTimesWhenSendAsyncFailed} times before claiming sending failure, which may yield
+     * message duplication and application developers are the one to resolve this potential issue.
+     *
+     * @param destination  formats: `topicName:tags`
+     * @param message      {@link org.springframework.messaging.Message}
+     * @param sendCallback {@link SendCallback}
+     */
+    public void asyncSend(String destination, Message<?> message, SendCallback sendCallback) {
+        asyncSend(destination, message, sendCallback, producer.getSendMsgTimeout());
+    }
+
+    /**
+     * Same to {@link #asyncSend(String, Object, SendCallback)} with send timeout specified in addition.
+     *
+     * @param destination  formats: `topicName:tags`
+     * @param payload      the Object to use as payload
+     * @param sendCallback {@link SendCallback}
+     * @param timeout      send timeout with millis
+     */
+    public void asyncSend(String destination, Object payload, SendCallback sendCallback, long timeout) {
+        Message<?> message = this.doConvert(payload, null, null);
+        asyncSend(destination, message, sendCallback, timeout);
+    }
+
+    /**
+     * Same to {@link #asyncSend(String, Message, SendCallback)}.
+     *
+     * @param destination  formats: `topicName:tags`
+     * @param payload      the Object to use as payload
+     * @param sendCallback {@link SendCallback}
+     */
+    public void asyncSend(String destination, Object payload, SendCallback sendCallback) {
+        asyncSend(destination, payload, sendCallback, producer.getSendMsgTimeout());
+    }
+
+    /**
+     * Same to {@link #asyncSendOrderly(String, Message, String, SendCallback)} with send timeout specified in
+     * addition.
+     *
+     * @param destination  formats: `topicName:tags`
+     * @param message      {@link org.springframework.messaging.Message}
+     * @param hashKey      use this key to select queue. for example: orderId, productId ...
+     * @param sendCallback {@link SendCallback}
+     * @param timeout      send timeout with millis
+     */
+    public void asyncSendOrderly(String destination, Message<?> message, String hashKey, SendCallback sendCallback,
+                                 long timeout) {
+        if (Objects.isNull(message) || Objects.isNull(message.getPayload())) {
+            log.error("asyncSendOrderly failed. destination:{}, message is null ", destination);
+            throw new IllegalArgumentException("`message` and `message.payload` cannot be null");
+        }
+
+        try {
+            org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper,
+                charset, destination, message);
+            producer.send(rocketMsg, messageQueueSelector, hashKey, sendCallback, timeout);
+        } catch (Exception e) {
+            log.error("asyncSendOrderly failed. destination:{}, message:{} ", destination, message);
+            throw new MessagingException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Same to {@link #asyncSend(String, Message, SendCallback)} with send orderly with hashKey by specified.
+     *
+     * @param destination  formats: `topicName:tags`
+     * @param message      {@link org.springframework.messaging.Message}
+     * @param hashKey      use this key to select queue. for example: orderId, productId ...
+     * @param sendCallback {@link SendCallback}
+     */
+    public void asyncSendOrderly(String destination, Message<?> message, String hashKey, SendCallback sendCallback) {
+        asyncSendOrderly(destination, message, hashKey, sendCallback, producer.getSendMsgTimeout());
+    }
+
+    /**
+     * Same to {@link #asyncSendOrderly(String, Message, String, SendCallback)}.
+     *
+     * @param destination  formats: `topicName:tags`
+     * @param payload      the Object to use as payload
+     * @param hashKey      use this key to select queue. for example: orderId, productId ...
+     * @param sendCallback {@link SendCallback}
+     */
+    public void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback) {
+        asyncSendOrderly(destination, payload, hashKey, sendCallback, producer.getSendMsgTimeout());
+    }
+
+    /**
+     * Same to {@link #asyncSendOrderly(String, Object, String, SendCallback)} with send timeout specified in addition.
+     *
+     * @param destination  formats: `topicName:tags`
+     * @param payload      the Object to use as payload
+     * @param hashKey      use this key to select queue. for example: orderId, productId ...
+     * @param sendCallback {@link SendCallback}
+     * @param timeout      send timeout with millis
+     */
+    public void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback,
+                                 long timeout) {
+        Message<?> message = this.doConvert(payload, null, null);
+        asyncSendOrderly(destination, message, hashKey, sendCallback, timeout);
+    }
+
+    /**
+     * Similar to <a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol">UDP</a>, this method won't wait for
+     * acknowledgement from broker before return. Obviously, it has maximums throughput yet potentials of message loss.
+     * <p>
+     * One-way transmission is used for cases requiring moderate reliability, such as log collection.
+     *
+     * @param destination formats: `topicName:tags`
+     * @param message     {@link org.springframework.messaging.Message}
+     */
+    public void sendOneWay(String destination, Message<?> message) {
+        if (Objects.isNull(message) || Objects.isNull(message.getPayload())) {
+            log.error("sendOneWay failed. destination:{}, message is null ", destination);
+            throw new IllegalArgumentException("`message` and `message.payload` cannot be null");
+        }
+
+        try {
+            org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper,
+                charset, destination, message);
+            producer.sendOneway(rocketMsg);
+        } catch (Exception e) {
+            log.error("sendOneWay failed. destination:{}, message:{} ", destination, message);
+            throw new MessagingException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Same to {@link #sendOneWay(String, Message)}
+     *
+     * @param destination formats: `topicName:tags`
+     * @param payload     the Object to use as payload
+     */
+    public void sendOneWay(String destination, Object payload) {
+        Message<?> message = this.doConvert(payload, null, null);
+        sendOneWay(destination, message);
+    }
+
+    /**
+     * Same to {@link #sendOneWay(String, Message)} with send orderly with hashKey by specified.
+     *
+     * @param destination formats: `topicName:tags`
+     * @param message     {@link org.springframework.messaging.Message}
+     * @param hashKey     use this key to select queue. for example: orderId, productId ...
+     */
+    public void sendOneWayOrderly(String destination, Message<?> message, String hashKey) {
+        if (Objects.isNull(message) || Objects.isNull(message.getPayload())) {
+            log.error("sendOneWayOrderly failed. destination:{}, message is null ", destination);
+            throw new IllegalArgumentException("`message` and `message.payload` cannot be null");
+        }
+
+        try {
+            org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper,
+                charset, destination, message);
+            producer.sendOneway(rocketMsg, messageQueueSelector, hashKey);
+        } catch (Exception e) {
+            log.error("sendOneWayOrderly failed. destination:{}, message:{}", destination, message);
+            throw new MessagingException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Same to {@link #sendOneWayOrderly(String, Message, String)}
+     *
+     * @param destination formats: `topicName:tags`
+     * @param payload     the Object to use as payload
+     */
+    public void sendOneWayOrderly(String destination, Object payload, String hashKey) {
+        Message<?> message = this.doConvert(payload, null, null);
+        sendOneWayOrderly(destination, message, hashKey);
+    }
+
+    public void afterPropertiesSet() throws Exception {
+        Assert.notNull(producer, "Property 'producer' is required");
+        producer.start();
+    }
+
+    protected void doSend(String destination, Message<?> message) {
+        SendResult sendResult = syncSend(destination, message);
+        log.debug("send message to `{}` finished. result:{}", destination, sendResult);
+    }
+
+
+
+    @Override
+    protected Message<?> doConvert(Object payload, Map<String, Object> headers, MessagePostProcessor postProcessor) {
+        String content;
+        if (payload instanceof String) {
+            content = (String) payload;
+        } else {
+            // If payload not as string, use objectMapper change it.
+            try {
+                content = objectMapper.writeValueAsString(payload);
+            } catch (JsonProcessingException e) {
+                log.error("convert payload to String failed. payload:{}", payload);
+                throw new RuntimeException("convert to payload to String failed.", e);
+            }
+        }
+
+        MessageBuilder<?> builder = MessageBuilder.withPayload(content);
+        if (headers != null) {
+            builder.copyHeaders(headers);
+        }
+        builder.setHeaderIfAbsent(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN);
+
+        Message<?> message = builder.build();
+        if (postProcessor != null) {
+            message = postProcessor.postProcessMessage(message);
+        }
+        return message;
+    }
+
+    @Override
+    public void destroy() {
+        if (Objects.nonNull(producer)) {
+            producer.shutdown();
+        }
+
+        for (Map.Entry<String, TransactionMQProducer> kv : cache.entrySet()) {
+            if (Objects.nonNull(kv.getValue())) {
+                kv.getValue().shutdown();
+            }
+        }
+        cache.clear();
+    }
+
+    private String getTxProducerGroupName(String name) {
+        return name == null ? RocketMQConfigUtils.ROCKETMQ_TRANSACTION_DEFAULT_GLOBAL_NAME : name;
+    }
+
+    private TransactionMQProducer stageMQProducer(String name) throws MessagingException {
+        name = getTxProducerGroupName(name);
+
+        TransactionMQProducer cachedProducer = cache.get(name);
+        if (cachedProducer == null) {
+            throw new MessagingException(
+                String.format("Can not found MQProducer '%s' in cache! please define @RocketMQLocalTransactionListener class or invoke createOrGetStartedTransactionMQProducer() to create it firstly", name));
+        }
+
+        return cachedProducer;
+    }
+
+    /**
+     * Send Spring Message in Transaction
+     *
+     * @param txProducerGroup the validate txProducerGroup name, set null if using the default name
+     * @param destination     destination formats: `topicName:tags`
+     * @param message         message {@link org.springframework.messaging.Message}
+     * @param arg             ext arg
+     * @return TransactionSendResult
+     * @throws MessagingException
+     */
+    public TransactionSendResult sendMessageInTransaction(final String txProducerGroup, final String destination, final Message<?> message, final Object arg) throws MessagingException {
+        try {
+            TransactionMQProducer txProducer = this.stageMQProducer(txProducerGroup);
+            org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper,
+                charset, destination, message);
+            return txProducer.sendMessageInTransaction(rocketMsg, arg);
+        } catch (MQClientException e) {
+            throw RocketMQUtil.convert(e);
+        }
+    }
+
+    /**
+     * Remove a TransactionMQProducer from cache by manual.
+     * <p>Note: RocketMQTemplate can release all cached producers when bean destroying, it is not recommended to directly
+     * use this method by user.
+     *
+     * @param txProducerGroup
+     * @throws MessagingException
+     */
+    public void removeTransactionMQProducer(String txProducerGroup) throws MessagingException {
+        txProducerGroup = getTxProducerGroupName(txProducerGroup);
+        if (cache.containsKey(txProducerGroup)) {
+            DefaultMQProducer cachedProducer = cache.get(txProducerGroup);
+            cachedProducer.shutdown();
+            cache.remove(txProducerGroup);
+        }
+    }
+
+    /**
+     * Create and start a transaction MQProducer, this new producer is cached in memory.
+     * <p>Note: This method is invoked internally when processing {@code @RocketMQLocalTransactionListener}, it is not
+     * recommended to directly use this method by user.
+     *
+     * @param txProducerGroup     Producer (group) name, unique for each producer
+     * @param transactionListener TransactoinListener impl class
+     * @param executorService     Nullable.
+     * @return true if producer is created and started; false if the named producer already exists in cache.
+     * @throws MessagingException
+     */
+    public boolean createAndStartTransactionMQProducer(String txProducerGroup, RocketMQLocalTransactionListener transactionListener,
+                                                       ExecutorService executorService) throws MessagingException {
+        txProducerGroup = getTxProducerGroupName(txProducerGroup);
+        if (cache.containsKey(txProducerGroup)) {
+            log.info(String.format("get TransactionMQProducer '%s' from cache", txProducerGroup));
+            return false;
+        }
+
+        TransactionMQProducer txProducer = createTransactionMQProducer(txProducerGroup, transactionListener, executorService);
+        try {
+            txProducer.start();
+            cache.put(txProducerGroup, txProducer);
+        } catch (MQClientException e) {
+            throw RocketMQUtil.convert(e);
+        }
+
+        return true;
+    }
+
+    private TransactionMQProducer createTransactionMQProducer(String name, RocketMQLocalTransactionListener transactionListener,
+                                                              ExecutorService executorService) {
+        Assert.notNull(producer, "Property 'producer' is required");
+        Assert.notNull(transactionListener, "Parameter 'transactionListener' is required");
+        TransactionMQProducer txProducer = new TransactionMQProducer(name);
+        txProducer.setTransactionListener(RocketMQUtil.convert(transactionListener));
+
+        txProducer.setNamesrvAddr(producer.getNamesrvAddr());
+        if (executorService != null) {
+            txProducer.setExecutorService(executorService);
+        }
+
+        txProducer.setSendMsgTimeout(producer.getSendMsgTimeout());
+        txProducer.setRetryTimesWhenSendFailed(producer.getRetryTimesWhenSendFailed());
+        txProducer.setRetryTimesWhenSendAsyncFailed(producer.getRetryTimesWhenSendAsyncFailed());
+        txProducer.setMaxMessageSize(producer.getMaxMessageSize());
+        txProducer.setCompressMsgBodyOverHowmuch(producer.getCompressMsgBodyOverHowmuch());
+        txProducer.setRetryAnotherBrokerWhenNotStoreOK(producer.isRetryAnotherBrokerWhenNotStoreOK());
+
+        return txProducer;
+    }
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java
new file mode 100644
index 0000000..1993035
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java
@@ -0,0 +1,423 @@
+/*
+ * 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.rocketmq.spring.support;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
+import org.apache.rocketmq.client.consumer.MessageSelector;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
+import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
+import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus;
+import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
+import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.spring.annotation.ConsumeMode;
+import org.apache.rocketmq.spring.annotation.MessageModel;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.annotation.SelectorType;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.SmartLifecycle;
+import org.springframework.util.Assert;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Objects;
+
+@SuppressWarnings("WeakerAccess")
+public class DefaultRocketMQListenerContainer implements InitializingBean, RocketMQListenerContainer, SmartLifecycle {
+    private final static Logger log = LoggerFactory.getLogger(DefaultRocketMQListenerContainer.class);
+
+    private long suspendCurrentQueueTimeMillis = 1000;
+
+    /**
+     * Message consume retry strategy<br> -1,no retry,put into DLQ directly<br> 0,broker control retry frequency<br>
+     * >0,client control retry frequency.
+     */
+    private int delayLevelWhenNextConsume = 0;
+
+    private String nameServer;
+
+    private String consumerGroup;
+
+    private String topic;
+
+    private int consumeThreadMax = 64;
+
+    private String charset = "UTF-8";
+
+    private ObjectMapper objectMapper = new ObjectMapper();
+
+    private RocketMQListener rocketMQListener;
+
+    private RocketMQMessageListener rocketMQMessageListener;
+
+    private DefaultMQPushConsumer consumer;
+
+    private Class messageType;
+
+    private boolean running;
+
+    // The following properties came from @RocketMQMessageListener.
+    private ConsumeMode consumeMode;
+    private SelectorType selectorType;
+    private String selectorExpression;
+    private MessageModel messageModel;
+
+    public long getSuspendCurrentQueueTimeMillis() {
+        return suspendCurrentQueueTimeMillis;
+    }
+
+    public void setSuspendCurrentQueueTimeMillis(long suspendCurrentQueueTimeMillis) {
+        this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis;
+    }
+
+    public int getDelayLevelWhenNextConsume() {
+        return delayLevelWhenNextConsume;
+    }
+
+    public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) {
+        this.delayLevelWhenNextConsume = delayLevelWhenNextConsume;
+    }
+
+    public String getNameServer() {
+        return nameServer;
+    }
+
+    public void setNameServer(String nameServer) {
+        this.nameServer = nameServer;
+    }
+
+    public String getConsumerGroup() {
+        return consumerGroup;
+    }
+
+    public void setConsumerGroup(String consumerGroup) {
+        this.consumerGroup = consumerGroup;
+    }
+
+    public String getTopic() {
+        return topic;
+    }
+
+    public void setTopic(String topic) {
+        this.topic = topic;
+    }
+
+    public int getConsumeThreadMax() {
+        return consumeThreadMax;
+    }
+
+    public String getCharset() {
+        return charset;
+    }
+
+    public void setCharset(String charset) {
+        this.charset = charset;
+    }
+
+    public ObjectMapper getObjectMapper() {
+        return objectMapper;
+    }
+
+    public void setObjectMapper(ObjectMapper objectMapper) {
+        this.objectMapper = objectMapper;
+    }
+
+
+    public RocketMQListener getRocketMQListener() {
+        return rocketMQListener;
+    }
+
+    public void setRocketMQListener(RocketMQListener rocketMQListener) {
+        this.rocketMQListener = rocketMQListener;
+    }
+
+    public RocketMQMessageListener getRocketMQMessageListener() {
+        return rocketMQMessageListener;
+    }
+
+    public void setRocketMQMessageListener(RocketMQMessageListener anno) {
+        this.rocketMQMessageListener = anno;
+
+        this.consumeMode = anno.consumeMode();
+        this.consumeThreadMax = anno.consumeThreadMax();
+        this.messageModel = anno.messageModel();
+        this.selectorExpression = anno.selectorExpression();
+        this.selectorType = anno.selectorType();
+    }
+
+    public ConsumeMode getConsumeMode() {
+        return consumeMode;
+    }
+
+    public SelectorType getSelectorType() {
+        return selectorType;
+    }
+
+    public String getSelectorExpression() {
+        return selectorExpression;
+    }
+
+    public MessageModel getMessageModel() {
+        return messageModel;
+    }
+
+    public DefaultMQPushConsumer getConsumer() {
+        return consumer;
+    }
+
+    public void setConsumer(DefaultMQPushConsumer consumer) {
+        this.consumer = consumer;
+    }
+
+    public void setupMessageListener(RocketMQListener rocketMQListener) {
+        this.rocketMQListener = rocketMQListener;
+    }
+
+    @Override
+    public void destroy() {
+        this.setRunning(false);
+        if (Objects.nonNull(consumer)) {
+            consumer.shutdown();
+        }
+        log.info("container destroyed, {}", this.toString());
+    }
+
+    @Override
+    public boolean isAutoStartup() {
+        return true;
+    }
+
+    @Override
+    public void stop(Runnable callback) {
+        stop();
+        callback.run();
+    }
+
+    @Override
+    public void start() {
+        if (this.isRunning()) {
+            throw new IllegalStateException("container already running. " + this.toString());
+        }
+
+        try {
+            consumer.start();
+        } catch (MQClientException e) {
+            throw new IllegalStateException("Failed to start RocketMQ push consumer", e);
+        }
+        this.setRunning(true);
+
+        log.info("running container: {}", this.toString());
+    }
+
+    @Override
+    public void stop() {
+        if (this.isRunning()) {
+            if (Objects.nonNull(consumer)) {
+                consumer.shutdown();
+            }
+            setRunning(false);
+        }
+    }
+
+    @Override
+    public boolean isRunning() {
+        return running;
+    }
+
+    private void setRunning(boolean running) {
+        this.running = running;
+    }
+
+    @Override
+    public int getPhase() {
+        // Returning Integer.MAX_VALUE only suggests that
+        // we will be the first bean to shutdown and last bean to start
+        return Integer.MAX_VALUE;
+    }
+
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        initRocketMQPushConsumer();
+
+        this.messageType = getMessageType();
+        log.debug("RocketMQ messageType: {}", messageType.getName());
+    }
+
+    @Override
+    public String toString() {
+        return "DefaultRocketMQListenerContainer{" +
+            "consumerGroup='" + consumerGroup + '\'' +
+            ", nameServer='" + nameServer + '\'' +
+            ", topic='" + topic + '\'' +
+            ", consumeMode=" + consumeMode +
+            ", selectorType=" + selectorType +
+            ", selectorExpression='" + selectorExpression + '\'' +
+            ", messageModel=" + messageModel +
+            '}';
+    }
+
+    public class DefaultMessageListenerConcurrently implements MessageListenerConcurrently {
+
+        @SuppressWarnings("unchecked")
+        public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
+            for (MessageExt messageExt : msgs) {
+                log.debug("received msg: {}", messageExt);
+                try {
+                    long now = System.currentTimeMillis();
+                    rocketMQListener.onMessage(doConvertMessage(messageExt));
+                    long costTime = System.currentTimeMillis() - now;
+                    log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime);
+                } catch (Exception e) {
+                    log.warn("consume message failed. messageExt:{}", messageExt, e);
+                    context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume);
+                    return ConsumeConcurrentlyStatus.RECONSUME_LATER;
+                }
+            }
+
+            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
+        }
+    }
+
+    public class DefaultMessageListenerOrderly implements MessageListenerOrderly {
+
+        @SuppressWarnings("unchecked")
+        public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {
+            for (MessageExt messageExt : msgs) {
+                log.debug("received msg: {}", messageExt);
+                try {
+                    long now = System.currentTimeMillis();
+                    rocketMQListener.onMessage(doConvertMessage(messageExt));
+                    long costTime = System.currentTimeMillis() - now;
+                    log.info("consume {} cost: {} ms", messageExt.getMsgId(), costTime);
+                } catch (Exception e) {
+                    log.warn("consume message failed. messageExt:{}", messageExt, e);
+                    context.setSuspendCurrentQueueTimeMillis(suspendCurrentQueueTimeMillis);
+                    return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;
+                }
+            }
+
+            return ConsumeOrderlyStatus.SUCCESS;
+        }
+    }
+
+
+    @SuppressWarnings("unchecked")
+    private Object doConvertMessage(MessageExt messageExt) {
+        if (Objects.equals(messageType, MessageExt.class)) {
+            return messageExt;
+        } else {
+            String str = new String(messageExt.getBody(), Charset.forName(charset));
+            if (Objects.equals(messageType, String.class)) {
+                return str;
+            } else {
+                // If msgType not string, use objectMapper change it.
+                try {
+                    return objectMapper.readValue(str, messageType);
+                } catch (Exception e) {
+                    log.info("convert failed. str:{}, msgType:{}", str, messageType);
+                    throw new RuntimeException("cannot convert message to " + messageType, e);
+                }
+            }
+        }
+    }
+
+    private Class getMessageType() {
+        Type[] interfaces = AopUtils.getTargetClass(rocketMQListener).getGenericInterfaces();
+        if (Objects.nonNull(interfaces)) {
+            for (Type type : interfaces) {
+                if (type instanceof ParameterizedType) {
+                    ParameterizedType parameterizedType = (ParameterizedType) type;
+                    if (Objects.equals(parameterizedType.getRawType(), RocketMQListener.class)) {
+                        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+                        if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) {
+                            return (Class) actualTypeArguments[0];
+                        } else {
+                            return Object.class;
+                        }
+                    }
+                }
+            }
+
+            return Object.class;
+        } else {
+            return Object.class;
+        }
+    }
+
+    private void initRocketMQPushConsumer() throws MQClientException {
+        Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required");
+        Assert.notNull(consumerGroup, "Property 'consumerGroup' is required");
+        Assert.notNull(nameServer, "Property 'nameServer' is required");
+        Assert.notNull(topic, "Property 'topic' is required");
+
+        consumer = new DefaultMQPushConsumer(consumerGroup);
+        consumer.setNamesrvAddr(nameServer);
+        consumer.setConsumeThreadMax(consumeThreadMax);
+        if (consumeThreadMax < consumer.getConsumeThreadMin()) {
+            consumer.setConsumeThreadMin(consumeThreadMax);
+        }
+
+        switch (messageModel) {
+            case BROADCASTING:
+                consumer.setMessageModel(org.apache.rocketmq.common.protocol.heartbeat.MessageModel.BROADCASTING);
+                break;
+            case CLUSTERING:
+                consumer.setMessageModel(org.apache.rocketmq.common.protocol.heartbeat.MessageModel.CLUSTERING);
+                break;
+        }
+
+        switch (selectorType) {
+            case TAG:
+                consumer.subscribe(topic, selectorExpression);
+                break;
+            case SQL92:
+                consumer.subscribe(topic, MessageSelector.bySql(selectorExpression));
+                break;
+            default:
+                throw new IllegalArgumentException("Property 'selectorType' was wrong.");
+        }
+
+        switch (consumeMode) {
+            case ORDERLY:
+                consumer.setMessageListener(new DefaultMessageListenerOrderly());
+                break;
+            case CONCURRENTLY:
+                consumer.setMessageListener(new DefaultMessageListenerConcurrently());
+                break;
+            default:
+                throw new IllegalArgumentException("Property 'consumeMode' was wrong.");
+        }
+
+        if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) {
+            ((RocketMQPushConsumerLifecycleListener) rocketMQListener).prepareStart(consumer);
+        }
+
+    }
+
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQConsumerLifecycleListener.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQConsumerLifecycleListener.java
new file mode 100644
index 0000000..8cc9b80
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQConsumerLifecycleListener.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.spring.support;
+
+public interface RocketMQConsumerLifecycleListener<T> {
+    void prepareStart(final T consumer);
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQHeaders.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQHeaders.java
new file mode 100644
index 0000000..e21aeab
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQHeaders.java
@@ -0,0 +1,34 @@
+/*
+ * 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.rocketmq.spring.support;
+
+/**
+ * Represents the RocketMQ message protocol that is used during the data exchange.
+ */
+public class RocketMQHeaders {
+    public static final String KEYS = "KEYS";
+    public static final String TAGS = "TAGS";
+    public static final String TOPIC = "TOPIC";
+    public static final String MESSAGE_ID = "MESSAGE_ID";
+    public static final String BORN_TIMESTAMP = "BORN_TIMESTAMP";
+    public static final String BORN_HOST = "BORN_HOST";
+    public static final String FLAG = "FLAG";
+    public static final String QUEUE_ID = "QUEUE_ID";
+    public static final String SYS_FLAG = "SYS_FLAG";
+    public static final String TRANSACTION_ID = "TRANSACTION_ID";
+    public static final String PROPERTIES = "PROPERTIES";
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQListenerContainer.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQListenerContainer.java
new file mode 100644
index 0000000..ee52de8
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQListenerContainer.java
@@ -0,0 +1,30 @@
+/*
+ * 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.rocketmq.spring.support;
+
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.springframework.beans.factory.DisposableBean;
+
+public interface RocketMQListenerContainer extends DisposableBean {
+
+    /**
+     * Setup the message listener to use. Throws an {@link IllegalArgumentException} if that message listener type is
+     * not supported.
+     */
+    void setupMessageListener(RocketMQListener<?> messageListener);
+}
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQUtil.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQUtil.java
new file mode 100644
index 0000000..7905be5
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQUtil.java
@@ -0,0 +1,168 @@
+/*
+ * 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.rocketmq.spring.support;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.producer.LocalTransactionState;
+import org.apache.rocketmq.client.producer.TransactionListener;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
+import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
+import org.springframework.messaging.MessageHeaders;
+import org.springframework.messaging.MessagingException;
+import org.springframework.messaging.support.MessageBuilder;
+import org.springframework.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.nio.charset.Charset;
+import java.util.Objects;
+
+public class RocketMQUtil {
+    private final static Logger log = LoggerFactory.getLogger(RocketMQUtil.class);
+
+    public static TransactionListener convert(RocketMQLocalTransactionListener listener) {
+        return new TransactionListener() {
+            @Override
+            public LocalTransactionState executeLocalTransaction(Message message, Object obj) {
+                RocketMQLocalTransactionState state = listener.executeLocalTransaction(convertToSpringMessage(message), obj);
+                return convertLocalTransactionState(state);
+            }
+
+            @Override
+            public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
+                RocketMQLocalTransactionState state = listener.checkLocalTransaction(convertToSpringMessage(messageExt));
+                return convertLocalTransactionState(state);
+            }
+        };
+    }
+
+    private static LocalTransactionState convertLocalTransactionState(RocketMQLocalTransactionState state) {
+        switch (state) {
+            case UNKNOWN:
+                return LocalTransactionState.UNKNOW;
+            case COMMIT:
+                return LocalTransactionState.COMMIT_MESSAGE;
+            case ROLLBACK:
+                return LocalTransactionState.ROLLBACK_MESSAGE;
+        }
+
+        // Never happen
+        log.warn("Failed to covert enum type RocketMQLocalTransactionState.%s", state);
+        return LocalTransactionState.UNKNOW;
+    }
+
+    public static MessagingException convert(MQClientException e) {
+        return new MessagingException(e.getErrorMessage(), e);
+    }
+
+    public static org.springframework.messaging.Message convertToSpringMessage(
+        org.apache.rocketmq.common.message.MessageExt message) {
+        org.springframework.messaging.Message retMessage =
+            MessageBuilder.withPayload(message.getBody()).
+                setHeader(RocketMQHeaders.KEYS, message.getKeys()).
+                setHeader(RocketMQHeaders.TAGS, message.getTags()).
+                setHeader(RocketMQHeaders.TOPIC, message.getTopic()).
+                setHeader(RocketMQHeaders.MESSAGE_ID, message.getMsgId()).
+                setHeader(RocketMQHeaders.BORN_TIMESTAMP, message.getBornTimestamp()).
+                setHeader(RocketMQHeaders.BORN_HOST, message.getBornHostString()).
+                setHeader(RocketMQHeaders.FLAG, message.getFlag()).
+                setHeader(RocketMQHeaders.QUEUE_ID, message.getQueueId()).
+                setHeader(RocketMQHeaders.SYS_FLAG, message.getSysFlag()).
+                setHeader(RocketMQHeaders.TRANSACTION_ID, message.getTransactionId()).
+                setHeader(RocketMQHeaders.PROPERTIES, message.getProperties()).
+                build();
+
+        return retMessage;
+    }
+
+    public static org.springframework.messaging.Message convertToSpringMessage(
+        org.apache.rocketmq.common.message.Message message) {
+        org.springframework.messaging.Message retMessage =
+            MessageBuilder.withPayload(message.getBody()).
+                setHeader(RocketMQHeaders.KEYS, message.getKeys()).
+                setHeader(RocketMQHeaders.TAGS, message.getTags()).
+                setHeader(RocketMQHeaders.TOPIC, message.getTopic()).
+                setHeader(RocketMQHeaders.FLAG, message.getFlag()).
+                setHeader(RocketMQHeaders.TRANSACTION_ID, message.getTransactionId()).
+                setHeader(RocketMQHeaders.PROPERTIES, message.getProperties()).
+                build();
+
+        return retMessage;
+    }
+
+    public static org.apache.rocketmq.common.message.Message convertToRocketMessage(
+        ObjectMapper objectMapper, String charset,
+        String destination, org.springframework.messaging.Message<?> message) {
+        Object payloadObj = message.getPayload();
+        byte[] payloads;
+
+        if (payloadObj instanceof String) {
+            payloads = ((String) payloadObj).getBytes(Charset.forName(charset));
+        } else {
+            try {
+                String jsonObj = objectMapper.writeValueAsString(payloadObj);
+                payloads = jsonObj.getBytes(Charset.forName(charset));
+            } catch (Exception e) {
+                throw new RuntimeException("convert to RocketMQ message failed.", e);
+            }
+        }
+
+        String[] tempArr = destination.split(":", 2);
+        String topic = tempArr[0];
+        String tags = "";
+        if (tempArr.length > 1) {
+            tags = tempArr[1];
+        }
+
+        org.apache.rocketmq.common.message.Message rocketMsg = new org.apache.rocketmq.common.message.Message(topic, tags, payloads);
+
+        MessageHeaders headers = message.getHeaders();
+        if (Objects.nonNull(headers) && !headers.isEmpty()) {
+            Object keys = headers.get(RocketMQHeaders.KEYS);
+            if (!StringUtils.isEmpty(keys)) { // if headers has 'KEYS', set rocketMQ message key
+                rocketMsg.setKeys(keys.toString());
+            }
+
+            Object flagObj = headers.getOrDefault("FLAG", "0");
+            int flag = 0;
+            try {
+                flag = Integer.parseInt(flagObj.toString());
+            } catch (NumberFormatException e) {
+                // Ignore it
+                log.info("flag must be integer, flagObj:{}", flagObj);
+            }
+            rocketMsg.setFlag(flag);
+
+            Object waitStoreMsgOkObj = headers.getOrDefault("WAIT_STORE_MSG_OK", "true");
+            boolean waitStoreMsgOK = Boolean.TRUE.equals(waitStoreMsgOkObj);
+            rocketMsg.setWaitStoreMsgOK(waitStoreMsgOK);
+
+            headers.entrySet().stream()
+                .filter(entry -> !Objects.equals(entry.getKey(), RocketMQHeaders.KEYS)
+                    && !Objects.equals(entry.getKey(), "FLAG")
+                    && !Objects.equals(entry.getKey(), "WAIT_STORE_MSG_OK")) // exclude "KEYS", "FLAG", "WAIT_STORE_MSG_OK"
+                .forEach(entry -> {
+                    rocketMsg.putUserProperty("USERS_" + entry.getKey(), String.valueOf(entry.getValue())); // add other properties with prefix "USERS_"
+                });
+
+        }
+
+        return rocketMsg;
+    }
+}
diff --git a/rocketmq-spring-boot/src/main/resources/META-INF/spring.factories b/rocketmq-spring-boot/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..92ff818
--- /dev/null
+++ b/rocketmq-spring-boot/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+org.apache.rocketmq.spring.config.RocketMQAutoConfiguration
\ No newline at end of file
diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
new file mode 100644
index 0000000..a841a74
--- /dev/null
+++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.spring.config;
+
+import org.apache.rocketmq.client.producer.DefaultMQProducer;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer;
+import org.junit.Test;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.boot.autoconfigure.AutoConfigurations;
+import org.springframework.boot.test.context.runner.ApplicationContextRunner;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RocketMQAutoConfigurationTest {
+    private ApplicationContextRunner runner = new ApplicationContextRunner()
+            .withConfiguration(AutoConfigurations.of(RocketMQAutoConfiguration.class));
+
+
+    @Test(expected = NoSuchBeanDefinitionException.class)
+    public void testRocketMQAutoConfigurationNotCreatedByDefault() {
+        runner.run(context -> context.getBean(RocketMQAutoConfiguration.class));
+    }
+
+
+    @Test(expected = NoSuchBeanDefinitionException.class)
+    public void testDefaultMQProducerNotCreatedByDefault() {
+        runner.run(context -> context.getBean(DefaultMQProducer.class));
+    }
+
+
+    @Test
+    public void testDefaultMQProducer() {
+        runner.withPropertyValues("spring.rocketmq.nameServer=127.0.0.1:9876",
+                "spring.rocketmq.producer.group=spring_rocketmq").
+                run((context) -> {
+                    assertThat(context).hasSingleBean(DefaultMQProducer.class);
+                    assertThat(context).hasSingleBean(RocketMQProperties.class);
+                });
+
+    }
+
+    @Test
+    public void testRocketMQListenerContainer() {
+        runner.withPropertyValues("spring.rocketmq.nameServer=127.0.0.1:9876").
+            withUserConfiguration(TestConfig.class).
+            run((context) -> {
+                // No producer on consume side
+                assertThat(context).doesNotHaveBean(DefaultMQProducer.class);
+                // Auto-create consume container if existing Bean annotated with @RocketMQMessageListener
+                assertThat(context).hasSingleBean(DefaultRocketMQListenerContainer.class);
+            });
+
+    }
+
+    @Configuration
+    static class TestConfig {
+
+        @Bean
+        public Object consumeListener() {
+            return new MyMessageListener();
+        }
+    }
+
+    @RocketMQMessageListener(consumerGroup = "abc", topic = "test")
+    static class MyMessageListener implements RocketMQListener {
+
+        @Override
+        public void onMessage(Object message) {
+
+        }
+    }
+}
+
diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/RocketMQUtilTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/RocketMQUtilTest.java
new file mode 100644
index 0000000..8690b93
--- /dev/null
+++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/RocketMQUtilTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.rocketmq.spring.support;
+
+
+import org.junit.Test;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.support.MessageBuilder;
+
+import static org.junit.Assert.assertTrue;
+
+public class RocketMQUtilTest {
+    @Test
+    public void testMessageBuilder() {
+        Message msg = MessageBuilder.withPayload("test").
+            setHeader("A", "test1").
+            setHeader("B", "test2").
+            build();
+        System.out.printf("header size=%d  %s %n", msg.getHeaders().size(), msg.getHeaders().toString());
+        assertTrue(msg.getHeaders().get("A") != null);
+        assertTrue(msg.getHeaders().get("B") != null);
+    }
+}
\ No newline at end of file
diff --git a/style/copyright/Apache.xml b/style/copyright/Apache.xml
new file mode 100644
index 0000000..e3e3dec
--- /dev/null
+++ b/style/copyright/Apache.xml
@@ -0,0 +1,23 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<component name="CopyrightManager">
+    <copyright>
+        <option name="myName" value="Apache" />
+        <option name="notice" value="Licensed to the Apache Software Foundation (ASF) under one or more&#10;contributor license agreements.  See the NOTICE file distributed with&#10;this work for additional information regarding copyright ownership.&#10;The ASF licenses this file to You under the Apache License, Version 2.0&#10;(the &quot;License&quot;); you may not use this file except in compliance with&#10;the License.  You may obtain a copy of the License at&#10;&#10;    http://www.a [...]
+    </copyright>
+</component>
\ No newline at end of file
diff --git a/style/copyright/profiles_settings.xml b/style/copyright/profiles_settings.xml
new file mode 100644
index 0000000..747c7e2
--- /dev/null
+++ b/style/copyright/profiles_settings.xml
@@ -0,0 +1,64 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<component name="CopyrightManager">
+    <settings default="Apache">
+        <module2copyright>
+            <element module="All" copyright="Apache"/>
+        </module2copyright>
+        <LanguageOptions name="GSP">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="HTML">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="JAVA">
+            <option name="fileTypeOverride" value="3" />
+            <option name="addBlankAfter" value="false" />
+        </LanguageOptions>
+        <LanguageOptions name="JSP">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="JSPX">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="MXML">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="Properties">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="block" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="SPI">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="block" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="XML">
+            <option name="fileTypeOverride" value="3"/>
+            <option name="prefixLines" value="false"/>
+        </LanguageOptions>
+        <LanguageOptions name="__TEMPLATE__">
+            <option name="separateBefore" value="true"/>
+            <option name="lenBefore" value="1"/>
+        </LanguageOptions>
+    </settings>
+</component>
\ No newline at end of file
diff --git a/style/rmq_checkstyle.xml b/style/rmq_checkstyle.xml
new file mode 100644
index 0000000..2e9658f
--- /dev/null
+++ b/style/rmq_checkstyle.xml
@@ -0,0 +1,135 @@
+<?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.
+  -->
+
+<!DOCTYPE module PUBLIC
+    "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+    "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+<!--Refer http://checkstyle.sourceforge.net/reports/google-java-style.html#s2.2-file-encoding -->
+<module name="Checker">
+
+    <property name="localeLanguage" value="en"/>
+
+    <!--To configure the check to report on the first instance in each file-->
+    <module name="FileTabCharacter"/>
+
+    <!-- header -->
+    <module name="RegexpHeader">
+        <property name="header" value="/\*\nLicensed to the Apache Software Foundation*"/>
+        <property name="fileExtensions" value="java" />
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="System\.out\.println"/>
+        <property name="message" value="Prohibit invoking System.out.println in source code !"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="//FIXME"/>
+        <property name="message" value="Recommended fix FIXME task !"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="//TODO"/>
+        <property name="message" value="Recommended fix TODO task !"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format" value="@alibaba"/>
+        <property name="message" value="Recommended remove @alibaba keyword!"/>
+    </module>
+    <module name="RegexpSingleline">
+        <property name="format" value="@taobao"/>
+        <property name="message" value="Recommended remove @taobao keyword!"/>
+    </module>
+    <module name="RegexpSingleline">
+        <property name="format" value="@author"/>
+        <property name="message" value="Recommended remove @author tag in javadoc!"/>
+    </module>
+
+    <module name="RegexpSingleline">
+        <property name="format"
+                  value=".*[\u3400-\u4DB5\u4E00-\u9FA5\u9FA6-\u9FBB\uF900-\uFA2D\uFA30-\uFA6A\uFA70-\uFAD9\uFF00-\uFFEF\u2E80-\u2EFF\u3000-\u303F\u31C0-\u31EF]+.*"/>
+        <property name="message" value="Not allow chinese character !"/>
+    </module>
+
+    <module name="FileLength">
+        <property name="max" value="3000"/>
+    </module>
+
+    <module name="TreeWalker">
+
+        <module name="UnusedImports">
+            <property name="processJavadoc" value="true"/>
+        </module>
+        <module name="RedundantImport"/>
+
+        <!--<module name="IllegalImport" />-->
+
+        <!--Checks that classes that override equals() also override hashCode()-->
+        <module name="EqualsHashCode"/>
+        <!--Checks for over-complicated boolean expressions. Currently finds code like if (topic == true), topic || true, !false, etc.-->
+        <module name="SimplifyBooleanExpression"/>
+        <module name="OneStatementPerLine"/>
+        <module name="UnnecessaryParentheses"/>
+        <!--Checks for over-complicated boolean return statements. For example the following code-->
+        <module name="SimplifyBooleanReturn"/>
+
+        <!--Check that the default is after all the cases in producerGroup switch statement-->
+        <module name="DefaultComesLast"/>
+        <!--Detects empty statements (standalone ";" semicolon)-->
+        <module name="EmptyStatement"/>
+        <!--Checks that long constants are defined with an upper ell-->
+        <module name="UpperEll"/>
+        <module name="ConstantName">
+            <property name="format" value="(^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$)|(^log$)"/>
+        </module>
+        <!--Checks that local, non-final variable names conform to producerGroup format specified by the format property-->
+        <module name="LocalVariableName"/>
+        <!--Validates identifiers for local, final variables, including catch parameters-->
+        <module name="LocalFinalVariableName"/>
+        <!--Validates identifiers for non-static fields-->
+        <module name="MemberName"/>
+        <!--Validates identifiers for class type parameters-->
+        <module name="ClassTypeParameterName">
+            <property name="format" value="^[A-Z0-9]*$"/>
+        </module>
+        <!--Validates identifiers for method type parameters-->
+        <module name="MethodTypeParameterName">
+            <property name="format" value="^[A-Z0-9]*$"/>
+        </module>
+        <module name="PackageName"/>
+        <module name="ParameterName"/>
+        <module name="StaticVariableName"/>
+        <module name="TypeName"/>
+        <!--Checks that there are no import statements that use the * notation-->
+        <module name="AvoidStarImport"/>
+
+        <!--whitespace-->
+        <module name="GenericWhitespace"/>
+        <module name="NoWhitespaceBefore"/>
+        <module name="NoWhitespaceAfter"/>
+        <module name="WhitespaceAround">
+            <property name="allowEmptyConstructors" value="true"/>
+            <property name="allowEmptyMethods" value="true"/>
+        </module>
+        <module name="Indentation"/>
+        <module name="MethodParamPad"/>
+        <module name="ParenPad"/>
+        <module name="TypecastParenPad"/>
+    </module>
+</module>
diff --git a/style/rmq_codeStyle.xml b/style/rmq_codeStyle.xml
new file mode 100644
index 0000000..9db075e
--- /dev/null
+++ b/style/rmq_codeStyle.xml
@@ -0,0 +1,157 @@
+<!--
+  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.
+  -->
+
+<code_scheme name="rocketmq">
+    <option name="USE_SAME_INDENTS" value="true"/>
+    <option name="IGNORE_SAME_INDENTS_FOR_LANGUAGES" value="true"/>
+    <option name="OTHER_INDENT_OPTIONS">
+        <value>
+            <option name="INDENT_SIZE" value="4"/>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+            <option name="TAB_SIZE" value="4"/>
+            <option name="USE_TAB_CHARACTER" value="false"/>
+            <option name="SMART_TABS" value="false"/>
+            <option name="LABEL_INDENT_SIZE" value="0"/>
+            <option name="LABEL_INDENT_ABSOLUTE" value="false"/>
+            <option name="USE_RELATIVE_INDENTS" value="false"/>
+        </value>
+    </option>
+    <option name="PREFER_LONGER_NAMES" value="false"/>
+    <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="1000"/>
+    <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="1000"/>
+    <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
+        <value/>
+    </option>
+    <option name="IMPORT_LAYOUT_TABLE">
+        <value>
+            <package name="" withSubpackages="true" static="false"/>
+            <emptyLine/>
+            <package name="" withSubpackages="true" static="true"/>
+        </value>
+    </option>
+    <option name="JD_ALIGN_PARAM_COMMENTS" value="false"/>
+    <option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false"/>
+    <option name="JD_P_AT_EMPTY_LINES" value="false"/>
+    <option name="JD_KEEP_INVALID_TAGS" value="false"/>
+    <option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true"/>
+    <option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
+    <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+    <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+    <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+    <option name="ELSE_ON_NEW_LINE" value="true"/>
+    <option name="WHILE_ON_NEW_LINE" value="true"/>
+    <option name="CATCH_ON_NEW_LINE" value="true"/>
+    <option name="FINALLY_ON_NEW_LINE" value="true"/>
+    <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+    <option name="ALIGN_MULTILINE_FOR" value="false"/>
+    <option name="SPACE_AFTER_TYPE_CAST" value="false"/>
+    <option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true"/>
+    <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+    <option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true"/>
+    <option name="LABELED_STATEMENT_WRAP" value="1"/>
+    <option name="WRAP_COMMENTS" value="true"/>
+    <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+    <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+    <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+    <JavaCodeStyleSettings>
+        <option name="CLASS_NAMES_IN_JAVADOC" value="3"/>
+    </JavaCodeStyleSettings>
+    <XML>
+        <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true"/>
+    </XML>
+    <ADDITIONAL_INDENT_OPTIONS fileType="haml">
+        <option name="INDENT_SIZE" value="2"/>
+    </ADDITIONAL_INDENT_OPTIONS>
+    <codeStyleSettings language="Groovy">
+        <option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
+        <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="ELSE_ON_NEW_LINE" value="true"/>
+        <option name="CATCH_ON_NEW_LINE" value="true"/>
+        <option name="FINALLY_ON_NEW_LINE" value="true"/>
+        <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+        <option name="ALIGN_MULTILINE_FOR" value="false"/>
+        <option name="SPACE_AFTER_TYPE_CAST" value="false"/>
+        <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+        <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+        <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+        <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+        <indentOptions>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+    <codeStyleSettings language="HOCON">
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+    </codeStyleSettings>
+    <codeStyleSettings language="JAVA">
+        <option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
+        <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="ELSE_ON_NEW_LINE" value="true"/>
+        <option name="WHILE_ON_NEW_LINE" value="true"/>
+        <option name="CATCH_ON_NEW_LINE" value="true"/>
+        <option name="FINALLY_ON_NEW_LINE" value="true"/>
+        <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+        <option name="ALIGN_MULTILINE_FOR" value="false"/>
+        <option name="SPACE_AFTER_TYPE_CAST" value="false"/>
+        <option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true"/>
+        <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+        <option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true"/>
+        <option name="LABELED_STATEMENT_WRAP" value="1"/>
+        <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+        <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+        <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+        <indentOptions>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+    <codeStyleSettings language="JSON">
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+    </codeStyleSettings>
+    <codeStyleSettings language="Scala">
+        <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
+        <option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
+        <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
+        <option name="ELSE_ON_NEW_LINE" value="true"/>
+        <option name="WHILE_ON_NEW_LINE" value="true"/>
+        <option name="CATCH_ON_NEW_LINE" value="true"/>
+        <option name="FINALLY_ON_NEW_LINE" value="true"/>
+        <option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
+        <option name="ALIGN_MULTILINE_FOR" value="false"/>
+        <option name="METHOD_PARAMETERS_WRAP" value="1"/>
+        <option name="METHOD_ANNOTATION_WRAP" value="1"/>
+        <option name="CLASS_ANNOTATION_WRAP" value="1"/>
+        <option name="FIELD_ANNOTATION_WRAP" value="1"/>
+        <option name="PARENT_SETTINGS_INSTALLED" value="true"/>
+        <indentOptions>
+            <option name="INDENT_SIZE" value="4"/>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+            <option name="TAB_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+    <codeStyleSettings language="XML">
+        <indentOptions>
+            <option name="CONTINUATION_INDENT_SIZE" value="4"/>
+        </indentOptions>
+    </codeStyleSettings>
+</code_scheme>
\ No newline at end of file


[rocketmq-spring] 25/37: Fix [ISSUE-9] Please do not use usage: spring [--help] [--version] []

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 09b1e79944eea8c3fe6bc71f7b4427c5032e5e4e
Author: walking98 <wi...@gmail.com>
AuthorDate: Wed Dec 19 10:04:51 2018 +0800

    Fix [ISSUE-9] Please do not use usage: spring [--help] [--version]
           <command> [<args>]
    
    Available commands are:
    
      run [options] <files> [--] [args]
        Run a spring groovy script
    
      grab
        Download a spring groovy script's dependencies to ./repository
    
      jar [options] <jar-name> <files>
        Create a self-contained executable jar file from a Spring Groovy script
    
      war [options] <war-name> <files>
        Create a self-contained executable war file from a Spring Groovy script
    
      install [options] <coordinates>
        Install dependencies to the lib/ext directory
    
      uninstall [options] <coordinates>
        Uninstall dependencies from the lib/ext directory
    
      init [options] [location]
        Initialize a new project using Spring Initializr (start.spring.io)
    
      encodepassword [options] <password to encode>
        Encode a password for use with Spring Security
    
      shell
        Start a nested shell
    
    Common options:
    
      -d, --debug Verbose mode
        Print additional status information for the command you are running
    
    See 'spring help <command>' for more information on a specific command. as a prefix for configuration properties
---
 README.md                                            | 20 ++++++++++----------
 README_zh_CN.md                                      | 20 ++++++++++----------
 .../springboot/consumer/OrderPaidEventConsumer.java  |  2 +-
 .../samples/springboot/consumer/StringConsumer.java  |  2 +-
 .../consumer/StringTransactionalConsumer.java        |  2 +-
 .../src/main/resources/application.properties        | 12 +++++++-----
 .../samples/springboot/ProducerApplication.java      |  8 ++++----
 .../src/main/resources/application.properties        | 14 ++++++++------
 .../spring/config/RocketMQAutoConfiguration.java     |  8 ++++----
 .../rocketmq/spring/config/RocketMQProperties.java   |  2 +-
 .../spring/config/RocketMQAutoConfigurationTest.java | 10 +++++-----
 11 files changed, 52 insertions(+), 48 deletions(-)

diff --git a/README.md b/README.md
index fc4689e..9f42552 100644
--- a/README.md
+++ b/README.md
@@ -54,8 +54,8 @@ Note: Current RELEASE.VERSION=2.0.1-SNAPSHOT (public review phase)
 
 ```properties
 ## application.properties
-spring.rocketmq.name-server=127.0.0.1:9876
-spring.rocketmq.producer.group=my-group
+rocketmq.name-server=127.0.0.1:9876
+rocketmq.producer.group=my-group
 ```
 
 > Note:
@@ -93,12 +93,12 @@ public class ProducerApplication implements CommandLineRunner{
 > More relevant configurations for producing:
 >
 > ```properties
-> spring.rocketmq.producer.retry-times-when-send-async-failed=0
-> spring.rocketmq.producer.send-message-timeout=300000
-> spring.rocketmq.producer.compress-message-body-threshold=4096
-> spring.rocketmq.producer.max-message-size=4194304
-> spring.rocketmq.producer.retry-another-broker-when-not-store-ok=false
-> spring.rocketmq.producer.retry-times-when-send-failed=2
+> rocketmq.producer.retry-times-when-send-async-failed=0
+> rocketmq.producer.send-message-timeout=300000
+> rocketmq.producer.compress-message-body-threshold=4096
+> rocketmq.producer.max-message-size=4194304
+> rocketmq.producer.retry-another-broker-when-not-store-ok=false
+> rocketmq.producer.retry-times-when-send-failed=2
 > ```
 
 
@@ -147,7 +147,7 @@ public class ProducerApplication implements CommandLineRunner{
 
 ```properties
 ## application.properties
-spring.rocketmq.name-server=127.0.0.1:9876
+rocketmq.name-server=127.0.0.1:9876
 ```
 
 > Note:
@@ -191,7 +191,7 @@ public class ConsumerApplication{
 
 1. How to connected many `nameserver` on production environment?
 
-    `spring.rocketmq.nameServer` support the configuration of multiple `nameserver`, separated by `;`. For example: `172.19.0.1: 9876; 172.19.0.2: 9876`
+    `rocketmq.name-server` support the configuration of multiple `nameserver`, separated by `;`. For example: `172.19.0.1: 9876; 172.19.0.2: 9876`
 
 1. When was `rocketMQTemplate` destroyed?
 
diff --git a/README_zh_CN.md b/README_zh_CN.md
index 8b4d136..82bb24e 100644
--- a/README_zh_CN.md
+++ b/README_zh_CN.md
@@ -45,8 +45,8 @@
 
 ```properties
 ## application.properties
-spring.rocketmq.name-server=127.0.0.1:9876
-spring.rocketmq.producer.group=my-group
+rocketmq.name-server=127.0.0.1:9876
+rocketmq.producer.group=my-group
 ```
 
 > 注意:
@@ -125,12 +125,12 @@ public class ProducerApplication implements CommandLineRunner{
 > 更多发送相关配置
 >
 > ```properties
-> spring.rocketmq.producer.retry-times-when-send-async-failed=0
-> spring.rocketmq.producer.send-message-timeout=300000
-> spring.rocketmq.producer.compress-message-body-threshold=4096
-> spring.rocketmq.producer.max-message-size=4194304
-> spring.rocketmq.producer.retry-another-broker-when-not-store-ok=false
-> spring.rocketmq.producer.retry-times-when-send-failed=2
+> rocketmq.producer.retry-times-when-send-async-failed=0
+> rocketmq.producer.send-message-timeout=300000
+> rocketmq.producer.compress-message-body-threshold=4096
+> rocketmq.producer.max-message-size=4194304
+> rocketmq.producer.retry-another-broker-when-not-store-ok=false
+> rocketmq.producer.retry-times-when-send-failed=2
 > ```
 
 
@@ -138,7 +138,7 @@ public class ProducerApplication implements CommandLineRunner{
 
 ```properties
 ## application.properties
-spring.rocketmq.name-server=127.0.0.1:9876
+rocketmq.name-server=127.0.0.1:9876
 ```
 
 > 注意:
@@ -183,7 +183,7 @@ public class ConsumerApplication{
 
 1. 生产环境有多个`nameserver`该如何连接?
 
-   `spring.rocketmq.nameServer`支持配置多个`nameserver`地址,采用`;`分隔即可。例如:`172.19.0.1:9876;172.19.0.2:9876`
+   `rocketmq.name-server`支持配置多个`nameserver`地址,采用`;`分隔即可。例如:`172.19.0.1:9876;172.19.0.2:9876`
 
 1. `rocketMQTemplate`在什么时候被销毁?
 
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/OrderPaidEventConsumer.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/OrderPaidEventConsumer.java
index 774cd23..677e0ea 100644
--- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/OrderPaidEventConsumer.java
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/OrderPaidEventConsumer.java
@@ -26,7 +26,7 @@ import org.springframework.stereotype.Service;
  * OrderPaidEventConsumer
  */
 @Service
-@RocketMQMessageListener(topic = "${spring.rocketmq.orderTopic}", consumerGroup = "order-paid-consumer")
+@RocketMQMessageListener(topic = "${demo.rocketmq.orderTopic}", consumerGroup = "order-paid-consumer")
 public class OrderPaidEventConsumer implements RocketMQListener<OrderPaidEvent> {
 
     @Override
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumer.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumer.java
index 370e847..2b90c69 100644
--- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumer.java
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumer.java
@@ -25,7 +25,7 @@ import org.springframework.stereotype.Service;
  * RocketMQMessageListener
  */
 @Service
-@RocketMQMessageListener(topic = "${spring.rocketmq.topic}", consumerGroup = "string_consumer")
+@RocketMQMessageListener(topic = "${demo.rocketmq.topic}", consumerGroup = "string_consumer")
 public class StringConsumer implements RocketMQListener<String> {
     @Override
     public void onMessage(String message) {
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringTransactionalConsumer.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringTransactionalConsumer.java
index 5eebcc8..be5d08d 100644
--- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringTransactionalConsumer.java
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringTransactionalConsumer.java
@@ -25,7 +25,7 @@ import org.springframework.stereotype.Service;
  * StringTransactionalConsumer
  */
 @Service
-@RocketMQMessageListener(topic = "${spring.rocketmq.transTopic}", consumerGroup = "string_trans_consumer")
+@RocketMQMessageListener(topic = "${demo.rocketmq.transTopic}", consumerGroup = "string_trans_consumer")
 public class StringTransactionalConsumer implements RocketMQListener<String> {
     @Override
     public void onMessage(String message) {
diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/resources/application.properties b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/resources/application.properties
index bbdeed1..5f74d5d 100644
--- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/resources/application.properties
+++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/resources/application.properties
@@ -1,7 +1,9 @@
 spring.application.name=rocketmq-consume-demo
 
-spring.rocketmq.nameServer=localhost:9876
-spring.rocketmq.topic=string-topic
-spring.rocketmq.orderTopic=order-paid-topic
-spring.rocketmq.msgExtTopic=message-ext-topic
-spring.rocketmq.transTopic=spring-transaction-topic
+rocketmq.name-server=localhost:9876
+rocketmq.topic=string-topic
+
+# properties used in application code
+demo.rocketmq.orderTopic=order-paid-topic
+demo.rocketmq.msgExtTopic=message-ext-topic
+demo.rocketmq.transTopic=spring-transaction-topic
diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerApplication.java b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerApplication.java
index bec2450..d7ca208 100644
--- a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerApplication.java
+++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerApplication.java
@@ -46,13 +46,13 @@ public class ProducerApplication implements CommandLineRunner {
     private static final String TX_PGROUP_NAME = "myTxProducerGroup";
     @Resource
     private RocketMQTemplate rocketMQTemplate;
-    @Value("${spring.rocketmq.transTopic}")
+    @Value("${demo.rocketmq.transTopic}")
     private String springTransTopic;
-    @Value("${spring.rocketmq.topic}")
+    @Value("${demo.rocketmq.topic}")
     private String springTopic;
-    @Value("${spring.rocketmq.orderTopic}")
+    @Value("${demo.rocketmq.orderTopic}")
     private String orderPaidTopic;
-    @Value("${spring.rocketmq.msgExtTopic}")
+    @Value("${demo.rocketmq.msgExtTopic}")
     private String msgExtTopic;
 
     public static void main(String[] args) {
diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties
index f14b1ba..7965b28 100644
--- a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties
+++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties
@@ -1,6 +1,8 @@
-spring.rocketmq.name-server=localhost:9876
-spring.rocketmq.producer.group=my-group1
-spring.rocketmq.topic=string-topic
-spring.rocketmq.orderTopic=order-paid-topic
-spring.rocketmq.msgExtTopic=message-ext-topic
-spring.rocketmq.transTopic=spring-transaction-topic
\ No newline at end of file
+rocketmq.name-server=localhost:9876
+rocketmq.producer.group=my-group1
+
+# properties used in the application
+demo.rocketmq.topic=string-topic
+demo.rocketmq.orderTopic=order-paid-topic
+demo.rocketmq.msgExtTopic=message-ext-topic
+demo.rocketmq.transTopic=spring-transaction-topic
\ No newline at end of file
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
index b65dee1..10dfb5e 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQAutoConfiguration.java
@@ -38,19 +38,19 @@ import java.util.Objects;
 
 @Configuration
 @EnableConfigurationProperties(RocketMQProperties.class)
-@ConditionalOnProperty(prefix = "spring.rocketmq", value = "name-server")
+@ConditionalOnProperty(prefix = "rocketmq", value = "name-server")
 @Import(ListenerContainerConfiguration.class)
 public class RocketMQAutoConfiguration {
 
     @Bean
     @ConditionalOnMissingBean(DefaultMQProducer.class)
-    @ConditionalOnProperty(prefix = "spring.rocketmq", value = {"name-server", "producer.group"})
+    @ConditionalOnProperty(prefix = "rocketmq", value = {"name-server", "producer.group"})
     public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties) {
         RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer();
         String nameServer = rocketMQProperties.getNameServer();
         String groupName = producerConfig.getGroup();
-        Assert.hasText(nameServer, "[spring.rocketmq.name-server] must not be null");
-        Assert.hasText(groupName, "[spring.rocketmq.producer.group] must not be null");
+        Assert.hasText(nameServer, "[rocketmq.name-server] must not be null");
+        Assert.hasText(groupName, "[rocketmq.producer.group] must not be null");
 
         DefaultMQProducer producer = new DefaultMQProducer(groupName);
         producer.setNamesrvAddr(nameServer);
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
index 07e9e06..9c8ce89 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQProperties.java
@@ -20,7 +20,7 @@ package org.apache.rocketmq.spring.config;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 
 @SuppressWarnings("WeakerAccess")
-@ConfigurationProperties(prefix = "spring.rocketmq")
+@ConfigurationProperties(prefix = "rocketmq")
 public class RocketMQProperties {
 
     /**
diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
index c0fa370..3c09d01 100644
--- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
+++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/config/RocketMQAutoConfigurationTest.java
@@ -49,8 +49,8 @@ public class RocketMQAutoConfigurationTest {
 
     @Test
     public void testDefaultMQProducerWithRelaxPropertyName() {
-        runner.withPropertyValues("spring.rocketmq.nameServer=127.0.0.1:9876",
-                "spring.rocketmq.producer.group=spring_rocketmq").
+        runner.withPropertyValues("rocketmq.nameServer=127.0.0.1:9876",
+                "rocketmq.producer.group=spring_rocketmq").
                 run((context) -> {
                     assertThat(context).hasSingleBean(DefaultMQProducer.class);
                     assertThat(context).hasSingleBean(RocketMQProperties.class);
@@ -60,8 +60,8 @@ public class RocketMQAutoConfigurationTest {
 
     @Test
     public void testDefaultMQProducer() {
-        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876",
-            "spring.rocketmq.producer.group=spring_rocketmq").
+        runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876",
+            "rocketmq.producer.group=spring_rocketmq").
             run((context) -> {
                 assertThat(context).hasSingleBean(DefaultMQProducer.class);
             });
@@ -70,7 +70,7 @@ public class RocketMQAutoConfigurationTest {
 
     @Test
     public void testRocketMQListenerContainer() {
-        runner.withPropertyValues("spring.rocketmq.name-server=127.0.0.1:9876").
+        runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876").
             withUserConfiguration(TestConfig.class).
             run((context) -> {
                 // No producer on consume side


[rocketmq-spring] 23/37: Update ISSUE_TEMPLATE.md

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit cfe14b83b57b4d738a679247465fdf2ba99b8c78
Author: von gosling <vo...@apache.org>
AuthorDate: Tue Dec 18 23:34:00 2018 +0800

    Update ISSUE_TEMPLATE.md
---
 .github/ISSUE_TEMPLATE.md | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 2cd7924..6d6dcd2 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -22,10 +22,4 @@ Any question or RocketMQ proposal please use our [mailing lists](http://rocketmq
 
 2. Provide any additional detail on your proposed use case for this feature.
 
-2. Indicate the importance of this issue to you (blocker, must-have, should-have, nice-to-have). Are you currently using any workarounds to address this issue?
-
-4. If there are some sub-tasks using -[] for each subtask and create a corresponding issue to map to the sub task:
-
-- [sub-task1-issue-number](example_sub_issue1_link_here): sub-task1 description here, 
-- [sub-task2-issue-number](example_sub_issue2_link_here): sub-task2 description here,
-- ...
\ No newline at end of file
+3. Indicate the importance of this issue to you (blocker, must-have, should-have, nice-to-have). Are you currently using any workarounds to address this issue?


[rocketmq-spring] 04/37: Merge pull request #1 from walking98/master

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 3f89080df8f797cad0d1f9eb8badb5050b09a553
Merge: 6302fca 0e777d2
Author: von gosling <vo...@apache.org>
AuthorDate: Thu Dec 6 17:32:46 2018 +0800

    Merge pull request #1 from walking98/master
    
    First release of RocketMQ-spring-boot from incubating, version as 2.0.0

 .github/ISSUE_TEMPLATE.md                          |  31 ++
 .github/PULL_REQUEST_TEMPLATE.md                   |  20 +
 .gitignore                                         |  13 +
 LICENSE                                            | 202 +++++++
 NOTICE                                             |   5 +
 README.md                                          | 278 +++++++++-
 README_zh_CN.md                                    | 268 +++++++++
 pom.xml                                            |  80 +++
 rocketmq-spring-boot-parent/pom.xml                | 177 ++++++
 rocketmq-spring-boot-samples/LICENSE               | 202 +++++++
 rocketmq-spring-boot-samples/README.md             |  38 ++
 rocketmq-spring-boot-samples/README_zh_CN.md       |  48 ++
 rocketmq-spring-boot-samples/pom.xml               |  89 +++
 .../rocketmq-consume-demo/pom.xml                  |  31 ++
 .../samples/springboot/ConsumerApplication.java    |  33 ++
 .../samples/springboot/consumer/Checker.java       |  44 ++
 .../springboot/consumer/MessageExtConsumer.java    |  46 ++
 .../consumer/OrderPaidEventConsumer.java           |  36 ++
 .../springboot/consumer/StringConsumer.java        |  34 ++
 .../consumer/StringTransactionalConsumer.java      |  34 ++
 .../samples/springboot/domain/OrderPaidEvent.java  |  54 ++
 .../src/main/resources/application.properties      |   7 +
 .../rocketmq-produce-demo/pom.xml                  |  32 ++
 .../samples/springboot/ProducerApplication.java    | 171 ++++++
 .../samples/springboot/domain/OrderPaidEvent.java  |  50 ++
 .../src/main/resources/application.properties      |   6 +
 .../style/copyright/Apache.xml                     |  23 +
 .../style/copyright/profiles_settings.xml          |  64 +++
 .../style/rmq_checkstyle.xml                       | 135 +++++
 .../style/rmq_codeStyle.xml                        | 157 ++++++
 rocketmq-spring-boot-starter/pom.xml               |  51 ++
 rocketmq-spring-boot/README.md                     |   7 +
 rocketmq-spring-boot/pom.xml                       | 104 ++++
 .../rocketmq/spring/annotation/ConsumeMode.java    |  30 +
 .../rocketmq/spring/annotation/MessageModel.java   |  33 ++
 .../spring/annotation/RocketMQMessageListener.java |  72 +++
 .../annotation/RocketMQTransactionListener.java    |  69 +++
 .../rocketmq/spring/annotation/SelectorType.java   |  33 ++
 .../config/ListenerContainerConfiguration.java     | 133 +++++
 .../spring/config/RocketMQAutoConfiguration.java   | 104 ++++
 .../spring/config/RocketMQConfigUtils.java         |  29 +
 .../rocketmq/spring/config/RocketMQProperties.java | 144 +++++
 .../RocketMQTransactionAnnotationProcessor.java    | 110 ++++
 .../rocketmq/spring/config/TransactionHandler.java |  75 +++
 .../spring/config/TransactionHandlerRegistry.java  |  50 ++
 .../rocketmq/spring/core/RocketMQListener.java     |  22 +
 .../core/RocketMQLocalTransactionListener.java     |  25 +
 .../spring/core/RocketMQLocalTransactionState.java |  24 +
 .../RocketMQPushConsumerLifecycleListener.java     |  24 +
 .../rocketmq/spring/core/RocketMQTemplate.java     | 609 +++++++++++++++++++++
 .../support/DefaultRocketMQListenerContainer.java  | 423 ++++++++++++++
 .../support/RocketMQConsumerLifecycleListener.java |  22 +
 .../rocketmq/spring/support/RocketMQHeaders.java   |  34 ++
 .../spring/support/RocketMQListenerContainer.java  |  30 +
 .../rocketmq/spring/support/RocketMQUtil.java      | 168 ++++++
 .../src/main/resources/META-INF/spring.factories   |   2 +
 .../config/RocketMQAutoConfigurationTest.java      |  92 ++++
 .../rocketmq/spring/support/RocketMQUtilTest.java  |  37 ++
 style/copyright/Apache.xml                         |  23 +
 style/copyright/profiles_settings.xml              |  64 +++
 style/rmq_checkstyle.xml                           | 135 +++++
 style/rmq_codeStyle.xml                            | 157 ++++++
 62 files changed, 5342 insertions(+), 1 deletion(-)


[rocketmq-spring] 26/37: Fixed for [ISSUE-7] ObjectMapper instantiated not necessary

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 505ad521752a7e03f64756f7a368f8ba6c0a4fdc
Author: walking98 <wi...@gmail.com>
AuthorDate: Wed Dec 19 10:18:25 2018 +0800

    Fixed for [ISSUE-7] ObjectMapper instantiated not necessary
---
 .../rocketmq/spring/support/DefaultRocketMQListenerContainer.java       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java
index ce1b388..c1a1759 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java
@@ -69,7 +69,7 @@ public class DefaultRocketMQListenerContainer implements InitializingBean, Rocke
 
     private String charset = "UTF-8";
 
-    private ObjectMapper objectMapper = new ObjectMapper();
+    private ObjectMapper objectMapper;
 
     private RocketMQListener rocketMQListener;
 


[rocketmq-spring] 05/37: Update README.md

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit ddd9d65a2124c59fdaac525e29d0d6bf4d7ea7e3
Author: von gosling <vo...@apache.org>
AuthorDate: Thu Dec 6 17:34:05 2018 +0800

    Update README.md
---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 9ca1362..c84b3e9 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
 
 ## Introduction
 
-This is a sub-repo of RocketMQ TLP (http://rocketmq.apache.org/), It aims to help developers quickly integrate [RocketMQ](http://rocketmq.apache.org/) in [Spring Boot](http://projects.spring.io/spring-boot/). Support the Spring Message specification to facilitate developers to quickly switch from other MQ to RocketMQ.
+Thi project aims to help developers quickly integrate [RocketMQ](http://rocketmq.apache.org/) in [Spring Boot](http://projects.spring.io/spring-boot/). Support the Spring Message specification to facilitate developers to quickly switch from other MQ to RocketMQ.
 
 ## How To Contribute
 


[rocketmq-spring] 27/37: Fix for code standard

Posted by di...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

dinglei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-spring.git

commit 9db9c3857d4a4c16e8119447e55133e602be3d51
Author: walking98 <wi...@gmail.com>
AuthorDate: Wed Dec 19 14:31:20 2018 +0800

    Fix for code standard
---
 .../rocketmq/spring/config/ListenerContainerConfiguration.java    | 6 ++++--
 .../apache/rocketmq/spring/config/TransactionHandlerRegistry.java | 8 +++++---
 .../java/org/apache/rocketmq/spring/core/RocketMQTemplate.java    | 2 ++
 .../rocketmq/spring/support/DefaultRocketMQListenerContainer.java | 5 +++++
 4 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
index 9f78a19..b159709 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/ListenerContainerConfiguration.java
@@ -124,7 +124,9 @@ public class ListenerContainerConfiguration implements ApplicationContextAware,
 
     private void validate(RocketMQMessageListener annotation) {
         if (annotation.consumeMode() == ConsumeMode.ORDERLY &&
-            annotation.messageModel() == MessageModel.BROADCASTING)
-            throw new BeanDefinitionValidationException("Bad annotation definition in @RocketMQMessageListener, messageModel BROADCASTING does not support ORDERLY message!");
+            annotation.messageModel() == MessageModel.BROADCASTING) {
+            throw new BeanDefinitionValidationException(
+                "Bad annotation definition in @RocketMQMessageListener, messageModel BROADCASTING does not support ORDERLY message!");
+        }
     }
 }
\ No newline at end of file
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java
index 73a1244..4365e41 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java
@@ -39,10 +39,12 @@ public class TransactionHandlerRegistry implements DisposableBean {
     }
 
     public void registerTransactionHandler(TransactionHandler handler) throws MQClientException {
-        if (listenerContainers.contains(handler.getName()))
+        if (listenerContainers.contains(handler.getName())) {
             throw new MQClientException(-1,
-                String.format("The transaction name [%s] has been defined in TransactionListener [%s]", handler.getName(),
-                    handler.getBeanName()));
+                String
+                    .format("The transaction name [%s] has been defined in TransactionListener [%s]", handler.getName(),
+                        handler.getBeanName()));
+        }
         listenerContainers.add(handler.getName());
 
         rocketMQTemplate.createAndStartTransactionMQProducer(handler.getName(), handler.getListener(), handler.getCheckExecutor());
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQTemplate.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQTemplate.java
index f8c7c64..0eb1053 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQTemplate.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQTemplate.java
@@ -447,11 +447,13 @@ public class RocketMQTemplate extends AbstractMessageSendingTemplate<String> imp
         sendOneWayOrderly(destination, message, hashKey);
     }
 
+    @Override
     public void afterPropertiesSet() throws Exception {
         Assert.notNull(producer, "Property 'producer' is required");
         producer.start();
     }
 
+    @Override
     protected void doSend(String destination, Message<?> message) {
         SendResult sendResult = syncSend(destination, message);
         log.debug("send message to `{}` finished. result:{}", destination, sendResult);
diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java
index c1a1759..7031dce 100644
--- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java
+++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java
@@ -194,6 +194,7 @@ public class DefaultRocketMQListenerContainer implements InitializingBean, Rocke
         this.consumer = consumer;
     }
 
+    @Override
     public void setupMessageListener(RocketMQListener rocketMQListener) {
         this.rocketMQListener = rocketMQListener;
     }
@@ -285,6 +286,7 @@ public class DefaultRocketMQListenerContainer implements InitializingBean, Rocke
     public class DefaultMessageListenerConcurrently implements MessageListenerConcurrently {
 
         @SuppressWarnings("unchecked")
+        @Override
         public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
             for (MessageExt messageExt : msgs) {
                 log.debug("received msg: {}", messageExt);
@@ -307,6 +309,7 @@ public class DefaultRocketMQListenerContainer implements InitializingBean, Rocke
     public class DefaultMessageListenerOrderly implements MessageListenerOrderly {
 
         @SuppressWarnings("unchecked")
+        @Override
         public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {
             for (MessageExt messageExt : msgs) {
                 log.debug("received msg: {}", messageExt);
@@ -396,6 +399,8 @@ public class DefaultRocketMQListenerContainer implements InitializingBean, Rocke
             case CLUSTERING:
                 consumer.setMessageModel(org.apache.rocketmq.common.protocol.heartbeat.MessageModel.CLUSTERING);
                 break;
+            default:
+                throw new IllegalArgumentException("Property 'messageModel' was wrong.");
         }
 
         switch (selectorType) {