From 5cfba3cf6d7a9b16f08f67f4d42b148623e9bebc Mon Sep 17 00:00:00 2001 From: wangxing Date: Thu, 30 May 2019 16:02:26 +0800 Subject: [PATCH 001/105] fix #83 --- .../apache/rocketmq/spring/support/RocketMQUtil.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 index dc354133..7cd500e8 100644 --- 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 @@ -26,16 +26,17 @@ import org.apache.rocketmq.common.message.MessageConst; import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.remoting.RPCHook; -import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; + import java.nio.charset.Charset; import java.util.Map; import java.util.Objects; @@ -104,7 +105,8 @@ private static void addUserProperties(Map properties, MessageBui if (!CollectionUtils.isEmpty(properties)) { properties.forEach((key, val) -> { if (!MessageConst.STRING_HASH_SET.contains(key) && !MessageHeaders.ID.equals(key) - && !MessageHeaders.TIMESTAMP.equals(key)) { + && !MessageHeaders.TIMESTAMP.equals(key) && + !MessageConst.STRING_HASH_SET.contains(key.replaceFirst("^" + RocketMQHeaders.PREFIX, ""))) { messageBuilder.setHeader(key, val); } }); From c1e8b30151df6c420ed3e272682d9d8d35d8512a Mon Sep 17 00:00:00 2001 From: wangxing Date: Thu, 30 May 2019 16:24:54 +0800 Subject: [PATCH 002/105] optimization --- .../java/org/apache/rocketmq/spring/support/RocketMQUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 7cd500e8..06ea118a 100644 --- 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 @@ -106,7 +106,7 @@ private static void addUserProperties(Map properties, MessageBui properties.forEach((key, val) -> { if (!MessageConst.STRING_HASH_SET.contains(key) && !MessageHeaders.ID.equals(key) && !MessageHeaders.TIMESTAMP.equals(key) && - !MessageConst.STRING_HASH_SET.contains(key.replaceFirst("^" + RocketMQHeaders.PREFIX, ""))) { + (!key.startsWith(RocketMQHeaders.PREFIX) || !MessageConst.STRING_HASH_SET.contains(key.replaceFirst("^" + RocketMQHeaders.PREFIX, "")))) { messageBuilder.setHeader(key, val); } }); From 7c5e260bd6a8a5f6da0246f87b3313c2023eb2a0 Mon Sep 17 00:00:00 2001 From: ShannonDing Date: Fri, 31 May 2019 19:17:38 +0800 Subject: [PATCH 003/105] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- rocketmq-spring-boot-parent/pom.xml | 4 ++-- rocketmq-spring-boot-starter/pom.xml | 2 +- rocketmq-spring-boot/pom.xml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index b5f533f2..921d16ea 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.0.3 + 2.0.4-SNAPSHOT pom Apache RocketMQ Spring Boot ${project.version} @@ -39,7 +39,7 @@ git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git - rocketmq-spring-all-2.0.3 + HEAD diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index adc5878b..3c66f186 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.0.3 + 2.0.4-SNAPSHOT ../pom.xml @@ -38,7 +38,7 @@ 2.0.5.RELEASE 5.1.0.RELEASE - 2.0.3 + 2.0.4-SNAPSHOT 4.5.1 1.7.25 diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml index 3ec565a9..5392ec82 100644 --- a/rocketmq-spring-boot-starter/pom.xml +++ b/rocketmq-spring-boot-starter/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.0.3 + 2.0.4-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml index b93e05cb..289a53ff 100644 --- a/rocketmq-spring-boot/pom.xml +++ b/rocketmq-spring-boot/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.0.3 + 2.0.4-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml From 4ee8b0ef418e1c55475565face64268973df9af4 Mon Sep 17 00:00:00 2001 From: wangxing Date: Tue, 4 Jun 2019 10:43:39 +0800 Subject: [PATCH 004/105] unit test --- .../rocketmq/spring/support/RocketMQUtilTest.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) 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 index 3704802d..3a0bc41b 100644 --- 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 @@ -16,16 +16,14 @@ */ package org.apache.rocketmq.spring.support; -import java.util.Arrays; - import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Test; import org.springframework.messaging.Message; import org.springframework.messaging.support.MessageBuilder; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import java.util.Arrays; + +import static org.junit.Assert.*; public class RocketMQUtilTest { @@ -88,6 +86,10 @@ public void testHeaderConvertToSpringMsg() { assertEquals(String.valueOf("1"), rocketMsg.getProperty("test")); assertEquals(String.valueOf("tags"), rocketMsg.getProperty(RocketMQHeaders.PREFIX + RocketMQHeaders.TAGS)); assertNull(rocketMsg.getTags()); + + rmqMsg.putUserProperty(RocketMQUtil.toRocketHeaderKey(RocketMQHeaders.TAGS), "tags2"); + springMsg = RocketMQUtil.convertToSpringMessage(rmqMsg); + assertEquals("tags", springMsg.getHeaders().get(RocketMQHeaders.PREFIX + RocketMQHeaders.TAGS)); } } \ No newline at end of file From 813f0d8100f9da98e12b947d7ff43062afe4e3eb Mon Sep 17 00:00:00 2001 From: lookcoder <19659120+lookcoder@users.noreply.github.com> Date: Tue, 4 Jun 2019 04:32:49 -0500 Subject: [PATCH 005/105] Set the correct transaction id identification key for subsequent operations. (#82) * Set the correct transaction id identification key for subsequent operations. --- .../rocketmq/samples/springboot/ProducerACLApplication.java | 2 +- .../apache/rocketmq/samples/springboot/ProducerApplication.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerACLApplication.java b/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerACLApplication.java index 1c403545..498c2e12 100644 --- a/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerACLApplication.java +++ b/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerACLApplication.java @@ -74,7 +74,7 @@ private void testTransaction() throws MessagingException { try { Message msg = MessageBuilder.withPayload("Hello RocketMQ " + i). - setHeader(RocketMQHeaders.KEYS, "KEY_" + i).build(); + setHeader(RocketMQHeaders.TRANSACTION_ID, "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", 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 9e49170e..8ab42e11 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 @@ -122,7 +122,7 @@ private void testTransaction() throws MessagingException { try { Message msg = MessageBuilder.withPayload("Hello RocketMQ " + i). - setHeader(RocketMQHeaders.KEYS, "KEY_" + i).build(); + setHeader(RocketMQHeaders.TRANSACTION_ID, "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", From 3e34dd99dbf0a461186ccfa0d38f370744600995 Mon Sep 17 00:00:00 2001 From: Luan Louis Date: Wed, 19 Jun 2019 16:46:28 +0800 Subject: [PATCH 006/105] [ISSUE #86] add feature: consumer listener enabled configuration (#87) #86 --- .../ListenerContainerConfiguration.java | 15 +++++++ .../autoconfigure/RocketMQProperties.java | 43 ++++++++++++++++++- .../RocketMQAutoConfigurationTest.java | 15 +++++++ 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index 2d6cb3fd..5d461bcf 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -38,6 +38,7 @@ import org.springframework.core.env.StandardEnvironment; import org.springframework.util.StringUtils; +import java.util.Collections; import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; @@ -87,6 +88,20 @@ private void registerContainer(String beanName, Object bean) { } RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class); + + String consumerGroup = this.environment.resolvePlaceholders(annotation.consumerGroup()); + String topic = this.environment.resolvePlaceholders(annotation.topic()); + + boolean listenerEnabled = + (boolean)rocketMQProperties.getConsumer().getListeners().getOrDefault(consumerGroup, Collections.EMPTY_MAP) + .getOrDefault(topic, true); + + if (!listenerEnabled) { + log.debug( + "Consumer Listener (group:{},topic:{}) is not enabled by configuration, will ignore initialization.", + consumerGroup, topic); + return; + } validate(annotation); String containerBeanName = String.format("%s_%s", DefaultRocketMQListenerContainer.class.getName(), diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java index 62ca2be6..832d0219 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java @@ -20,6 +20,9 @@ import org.apache.rocketmq.common.MixAll; import org.springframework.boot.context.properties.ConfigurationProperties; +import java.util.HashMap; +import java.util.Map; + @SuppressWarnings("WeakerAccess") @ConfigurationProperties(prefix = "rocketmq") public class RocketMQProperties { @@ -36,6 +39,16 @@ public class RocketMQProperties { private Producer producer; + /** + * Configure enable listener or not. + * In some particular cases, if you don't want the the listener is enabled when container startup, + * the configuration pattern is like this : + * rocketmq.consumer.listeners...enabled= + *

+ * the listener is enabled by default. + */ + private Consumer consumer = new Consumer(); + public String getNameServer() { return nameServer; } @@ -63,7 +76,7 @@ public void setProducer(RocketMQProperties.Producer producer) { public static class Producer { /** - * Name of producer. + * Group name of producer. */ private String group; @@ -207,4 +220,32 @@ public void setCustomizedTraceTopic(String customizedTraceTopic) { this.customizedTraceTopic = customizedTraceTopic; } } + + public Consumer getConsumer() { + return consumer; + } + + public void setConsumer(Consumer consumer) { + this.consumer = consumer; + } + + public static final class Consumer { + /** + * listener configuration container + * the pattern is like this: + * group1.topic1 = false + * group2.topic2 = true + * group3.topic3 = false + */ + private Map> listeners = new HashMap<>(); + + public Map> getListeners() { + return listeners; + } + + public void setListeners(Map> listeners) { + this.listeners = listeners; + } + } + } diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index 528e9161..d6138084 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -145,6 +145,21 @@ public void accept(AssertableApplicationContext context) throws Throwable { }); } + @Test + public void testConsumerListener() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", + "rocketmq.producer.group=spring_rocketmq", + "rocketmq.consumer.listeners.spring_rocketmq.FOO_TEST_TOPIC=false", + "rocketmq.consumer.listeners.spring_rocketmq.FOO_TEST_TOPIC2=true"). + run((context) -> { + RocketMQProperties rocketMQProperties = context.getBean(RocketMQProperties.class); + assertThat(rocketMQProperties.getConsumer().getListeners().get("spring_rocketmq").get("FOO_TEST_TOPIC").booleanValue()).isEqualTo(false); + assertThat(rocketMQProperties.getConsumer().getListeners().get("spring_rocketmq").get("FOO_TEST_TOPIC2").booleanValue()).isEqualTo(true); + }); + + } + + @Configuration static class TestConfig { From 508aa99a22c0e2aac89776d233fb1b196ba6f47d Mon Sep 17 00:00:00 2001 From: feng chunhai Date: Mon, 24 Jun 2019 19:31:25 +0800 Subject: [PATCH 007/105] resolve the placeholder for "listener.txProducerGroup()" --- .../spring/config/RocketMQTransactionAnnotationProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index a8022650..2713bad5 100644 --- 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 @@ -96,7 +96,7 @@ private void processTransactionListenerAnnotation(RocketMQTransactionListener li } TransactionHandler transactionHandler = new TransactionHandler(); transactionHandler.setBeanFactory(this.applicationContext.getAutowireCapableBeanFactory()); - transactionHandler.setName(listener.txProducerGroup()); + transactionHandler.setName(applicationContext.getEnvironment().resolvePlaceholders(listener.txProducerGroup())); transactionHandler.setBeanName(bean.getClass().getName()); transactionHandler.setListener((RocketMQLocalTransactionListener) bean); transactionHandler.setCheckExecutor(listener.corePoolSize(), listener.maximumPoolSize(), From ef63a5a7b5f49425c103f443f6dfb177b2e364f8 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 11 Jul 2019 11:31:01 +0800 Subject: [PATCH 008/105] update README typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f8edadce..c7504b8a 100644 --- a/README.md +++ b/README.md @@ -280,7 +280,7 @@ public class MyConsumer implements RocketMQListener { 1. How to connected many `nameserver` on production environment? - `rocketmq.name-server` 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? @@ -403,4 +403,4 @@ public class MyConsumer implements RocketMQListener { public class MyNameServerConsumer implements RocketMQListener { ... } - ``` \ No newline at end of file + ``` From 4de7a7004740ba6c6cbf626e282679cc29d1b335 Mon Sep 17 00:00:00 2001 From: feng chunhai Date: Fri, 26 Jul 2019 18:58:00 +0800 Subject: [PATCH 009/105] add test for "resolve the placeholder for listener.txProducerGroup() " --- .../RocketMQAutoConfigurationTest.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index d6138084..53c716ed 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -21,7 +21,10 @@ import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; import org.apache.rocketmq.spring.core.RocketMQListener; +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.DefaultRocketMQListenerContainer; import org.junit.Assert; @@ -34,6 +37,7 @@ import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.Message; import static org.assertj.core.api.Assertions.assertThat; @@ -159,6 +163,18 @@ public void testConsumerListener() { } + @Test + public void testRocketMQTransactionListener() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", + "rocketmq.producer.group=spring_rocketmq", + "demo.rocketmq.transaction.producer.group=transaction-group1"). + withUserConfiguration(TestTransactionListenerConfig.class). + run((context) -> { + assertThat(context).hasSingleBean(MyRocketMQLocalTransactionListener.class); + + }); + + } @Configuration static class TestConfig { @@ -218,6 +234,30 @@ public void onMessage(Object message) { } } + @Configuration + static class TestTransactionListenerConfig { + @Bean + public Object rocketMQLocalTransactionListener() { + return new MyRocketMQLocalTransactionListener(); + } + + } + + @RocketMQTransactionListener(txProducerGroup = "${demo.rocketmq.transaction.producer.group}") + static class MyRocketMQLocalTransactionListener implements RocketMQLocalTransactionListener { + + + @Override + public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { + return RocketMQLocalTransactionState.COMMIT; + } + + @Override + public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { + return RocketMQLocalTransactionState.COMMIT; + } + } + @Configuration static class ExtRocketMQTemplateConfig { From 99f706db93b3d636b46dd04866786978efadee8c Mon Sep 17 00:00:00 2001 From: feng chunhai Date: Mon, 29 Jul 2019 10:07:00 +0800 Subject: [PATCH 010/105] format code style --- .../RocketMQAutoConfigurationTest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index 53c716ed..18fdcca0 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -152,14 +152,14 @@ public void accept(AssertableApplicationContext context) throws Throwable { @Test public void testConsumerListener() { runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", - "rocketmq.producer.group=spring_rocketmq", - "rocketmq.consumer.listeners.spring_rocketmq.FOO_TEST_TOPIC=false", - "rocketmq.consumer.listeners.spring_rocketmq.FOO_TEST_TOPIC2=true"). - run((context) -> { - RocketMQProperties rocketMQProperties = context.getBean(RocketMQProperties.class); - assertThat(rocketMQProperties.getConsumer().getListeners().get("spring_rocketmq").get("FOO_TEST_TOPIC").booleanValue()).isEqualTo(false); - assertThat(rocketMQProperties.getConsumer().getListeners().get("spring_rocketmq").get("FOO_TEST_TOPIC2").booleanValue()).isEqualTo(true); - }); + "rocketmq.producer.group=spring_rocketmq", + "rocketmq.consumer.listeners.spring_rocketmq.FOO_TEST_TOPIC=false", + "rocketmq.consumer.listeners.spring_rocketmq.FOO_TEST_TOPIC2=true"). + run((context) -> { + RocketMQProperties rocketMQProperties = context.getBean(RocketMQProperties.class); + assertThat(rocketMQProperties.getConsumer().getListeners().get("spring_rocketmq").get("FOO_TEST_TOPIC").booleanValue()).isEqualTo(false); + assertThat(rocketMQProperties.getConsumer().getListeners().get("spring_rocketmq").get("FOO_TEST_TOPIC2").booleanValue()).isEqualTo(true); + }); } From 812212ff19ebc9ee9fb4e1d5b7c6f672f67272ca Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Mon, 29 Jul 2019 15:29:00 +0800 Subject: [PATCH 011/105] modify .travis.yml to make travis-ci work --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 24e6a65a..0d7d2a6c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,9 @@ notifications: language: java +jdk: + - oraclejdk8 + matrix: include: # On OSX, run with default JDK only. From 13bb2d49fccf16e32c161e640db11c57dbd70e05 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Mon, 29 Jul 2019 17:31:16 +0800 Subject: [PATCH 012/105] modify .travis.yml to make travis-ci work (add dist:trusty) --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0d7d2a6c..49be497f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ +dist: trusty + notifications: email: recipients: From aeb448a58c2a5c191063be3a49f8c056dd4cce58 Mon Sep 17 00:00:00 2001 From: shaolsh <40844985+shaolsh@users.noreply.github.com> Date: Tue, 20 Aug 2019 15:24:07 +0800 Subject: [PATCH 013/105] [ISSUE #117]Fix timeout failed in syncSendOrderly. [ISSUE #117]Fix timeout failed in syncSendOrderly --- .../java/org/apache/rocketmq/spring/core/RocketMQTemplate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 6b5d06c0..be4d1949 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 @@ -283,7 +283,7 @@ public SendResult syncSendOrderly(String destination, Object payload, String has */ 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()); + return syncSendOrderly(destination, message, hashKey, timeout); } /** * Same to {@link #asyncSend(String, Message, SendCallback)} with send timeout and delay level specified in addition. From 4e719a96e2eecc3b9d5269fe87abfde15c5b4f95 Mon Sep 17 00:00:00 2001 From: liuliu Date: Thu, 22 Aug 2019 21:32:19 +0800 Subject: [PATCH 014/105] fix:#103 support resolvePlaceholders for selectorExpression @RocketMQMessageListener(topic = "${demo.rocketmq.test.consumer.topic}",selectorExpression="${demo.rocketmq.test.consumer.tags}" ,consumerGroup = "${demo.rocketmq.test.consumer.group}") --- .../spring/autoconfigure/ListenerContainerConfiguration.java | 4 ++++ .../spring/support/DefaultRocketMQListenerContainer.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index 5d461bcf..efd70846 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -135,6 +135,10 @@ private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String container.setAccessChannel(AccessChannel.valueOf(accessChannel)); } container.setTopic(environment.resolvePlaceholders(annotation.topic())); + String tags = environment.resolvePlaceholders(annotation.selectorExpression()); + if (!StringUtils.isEmpty(tags)) { + container.setSelectorExpression(tags); + } container.setConsumerGroup(environment.resolvePlaceholders(annotation.consumerGroup())); container.setRocketMQMessageListener(annotation); container.setRocketMQListener((RocketMQListener) bean); 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 6a730107..53acfd5a 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 @@ -204,6 +204,10 @@ public SelectorType getSelectorType() { return selectorType; } + public void setSelectorExpression(String selectorExpression) { + this.selectorExpression = selectorExpression; + } + public String getSelectorExpression() { return selectorExpression; } From a380c885469c4bd30f8b5efc19390b0548668b4e Mon Sep 17 00:00:00 2001 From: liuliu Date: Thu, 22 Aug 2019 23:36:53 +0800 Subject: [PATCH 015/105] fix:#103 support resolvePlaceholders for selectorExpression codestyle check --- .../autoconfigure/ListenerContainerConfiguration.java | 8 ++++---- .../spring/support/DefaultRocketMQListenerContainer.java | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index efd70846..43411c49 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -135,10 +135,10 @@ private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String container.setAccessChannel(AccessChannel.valueOf(accessChannel)); } container.setTopic(environment.resolvePlaceholders(annotation.topic())); - String tags = environment.resolvePlaceholders(annotation.selectorExpression()); - if (!StringUtils.isEmpty(tags)) { - container.setSelectorExpression(tags); - } + String tags = environment.resolvePlaceholders(annotation.selectorExpression()); + if (!StringUtils.isEmpty(tags)) { + container.setSelectorExpression(tags); + } container.setConsumerGroup(environment.resolvePlaceholders(annotation.consumerGroup())); container.setRocketMQMessageListener(annotation); container.setRocketMQListener((RocketMQListener) bean); 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 53acfd5a..e31924da 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 @@ -204,10 +204,10 @@ public SelectorType getSelectorType() { return selectorType; } - public void setSelectorExpression(String selectorExpression) { - this.selectorExpression = selectorExpression; - } - + public void setSelectorExpression(String selectorExpression) { + this.selectorExpression = selectorExpression; + } + public String getSelectorExpression() { return selectorExpression; } From c2cd6efd431db9c4bf15ed1911567746ee63e960 Mon Sep 17 00:00:00 2001 From: duhenglucky Date: Fri, 30 Aug 2019 10:51:24 +0800 Subject: [PATCH 016/105] Upgrade rocketmq dependency to 4.5.2 --- 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 3c66f186..21cf25be 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -40,7 +40,7 @@ 2.0.4-SNAPSHOT - 4.5.1 + 4.5.2 1.7.25 2.9.7 From 908ea4812192b36789c46d230b2fa61f51f3c867 Mon Sep 17 00:00:00 2001 From: King <794220751@qq.com> Date: Tue, 10 Sep 2019 14:04:49 +0800 Subject: [PATCH 017/105] [ISSUE 99 & ISSUE 107] Fix the message was consumed twice because of the same instanceName --- .../samples/springboot/consumer/StringConsumerNewNS.java | 2 +- .../spring/support/DefaultRocketMQListenerContainer.java | 1 - .../java/org/apache/rocketmq/spring/support/RocketMQUtil.java | 4 +++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerNewNS.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerNewNS.java index 5d2c8727..4c7dfc09 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerNewNS.java +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerNewNS.java @@ -25,7 +25,7 @@ * RocketMQMessageListener */ @Service -@RocketMQMessageListener(nameServer = "${demo.rocketmq.myNameServer}", topic = "${demo.rocketmq.topic}", consumerGroup = "string_consumer") +@RocketMQMessageListener(nameServer = "${demo.rocketmq.myNameServer}", topic = "${demo.rocketmq.topic}", consumerGroup = "string_consumer_newns") public class StringConsumerNewNS implements RocketMQListener { @Override public void onMessage(String message) { 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 6a730107..c4b5d197 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 @@ -450,7 +450,6 @@ private void initRocketMQPushConsumer() throws MQClientException { consumer.setConsumeThreadMin(consumeThreadMax); } consumer.setConsumeTimeout(consumeTimeout); - consumer.setInstanceName(this.name); switch (messageModel) { case BROADCASTING: 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 index 06ea118a..d10cb1b6 100644 --- 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 @@ -22,6 +22,7 @@ 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.UtilAll; import org.apache.rocketmq.common.message.Message; import org.apache.rocketmq.common.message.MessageConst; import org.apache.rocketmq.common.message.MessageExt; @@ -211,7 +212,8 @@ public static String getInstanceName(RPCHook rpcHook, String identify) { SessionCredentials sessionCredentials = ((AclClientRPCHook) rpcHook).getSessionCredentials(); instanceName.append(sessionCredentials.getAccessKey()) .append(separator).append(sessionCredentials.getSecretKey()) - .append(separator).append(identify); + .append(separator).append(identify) + .append(separator).append(UtilAll.getPid()); return instanceName.toString(); } } From 95ca29260b9fa6b0cad860b87144e9e257c391bd Mon Sep 17 00:00:00 2001 From: liuliu Date: Fri, 27 Sep 2019 10:20:22 +0800 Subject: [PATCH 018/105] fix:#103 support resolvePlaceholders for selectorExpression codestyle --- .../spring/support/DefaultRocketMQListenerContainer.java | 1 - 1 file changed, 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 e31924da..eb6f778a 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 @@ -191,7 +191,6 @@ public void setRocketMQMessageListener(RocketMQMessageListener anno) { this.consumeMode = anno.consumeMode(); this.consumeThreadMax = anno.consumeThreadMax(); this.messageModel = anno.messageModel(); - this.selectorExpression = anno.selectorExpression(); this.selectorType = anno.selectorType(); this.consumeTimeout = anno.consumeTimeout(); } From f85574d7c4a2063d58392f5491df643e50591a1f Mon Sep 17 00:00:00 2001 From: liuliu Date: Fri, 27 Sep 2019 10:34:01 +0800 Subject: [PATCH 019/105] fix:#103 support resolvePlaceholders for selectorExpression codestyle --- .../spring/autoconfigure/ListenerContainerConfiguration.java | 5 +++-- .../spring/support/DefaultRocketMQListenerContainer.java | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index 43411c49..927bf44c 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -126,7 +126,9 @@ private void registerContainer(String beanName, Object bean) { private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String name, Object bean, RocketMQMessageListener annotation) { DefaultRocketMQListenerContainer container = new DefaultRocketMQListenerContainer(); - + + container.setRocketMQMessageListener(annotation); + String nameServer = environment.resolvePlaceholders(annotation.nameServer()); nameServer = StringUtils.isEmpty(nameServer) ? rocketMQProperties.getNameServer() : nameServer; String accessChannel = environment.resolvePlaceholders(annotation.accessChannel()); @@ -140,7 +142,6 @@ private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String container.setSelectorExpression(tags); } container.setConsumerGroup(environment.resolvePlaceholders(annotation.consumerGroup())); - container.setRocketMQMessageListener(annotation); container.setRocketMQListener((RocketMQListener) bean); container.setObjectMapper(objectMapper); container.setName(name); // REVIEW ME, use the same clientId or multiple? 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 eb6f778a..e31924da 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 @@ -191,6 +191,7 @@ public void setRocketMQMessageListener(RocketMQMessageListener anno) { this.consumeMode = anno.consumeMode(); this.consumeThreadMax = anno.consumeThreadMax(); this.messageModel = anno.messageModel(); + this.selectorExpression = anno.selectorExpression(); this.selectorType = anno.selectorType(); this.consumeTimeout = anno.consumeTimeout(); } From d8a38d3df69cc4922ec3a3bf9fc24d595732599e Mon Sep 17 00:00:00 2001 From: liuliu Date: Sat, 28 Sep 2019 16:16:17 +0800 Subject: [PATCH 020/105] fix:#103 support resolvePlaceholders for selectorExpression codestyle --- .../RocketMQAutoConfigurationTest.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index 18fdcca0..4457b95f 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -176,6 +176,27 @@ public void testRocketMQTransactionListener() { } + @Test + public void testPlaceholdersListenerContainer() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", + "demo.placeholders.consumer.group = abc3", + "demo.placeholders.consumer.topic = test", + "demo.placeholders.consumer.tags = tag1"). + withUserConfiguration(TestPlaceholdersConfig.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).hasBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1"); + assertThat(context).getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1"). + hasFieldOrPropertyWithValue("nameServer", "127.0.0.1:9876"). + hasFieldOrPropertyWithValue("consumerGroup", "abc3"). + hasFieldOrPropertyWithValue("topic", "test"). + hasFieldOrPropertyWithValue("selectorExpression", "tag1"); + }); + } + + @Configuration static class TestConfig { @@ -272,5 +293,24 @@ public RocketMQTemplate extRocketMQTemplate() { static class MyExtRocketMQTemplate extends RocketMQTemplate { } + + @Configuration + static class TestPlaceholdersConfig { + + @Bean + public Object consumeListener() { + return new TestPlaceholdersListener(); + } + + } + + @RocketMQMessageListener(consumerGroup = "${demo.placeholders.consumer.group}", topic = "${demo.placeholders.consumer.topic}", selectorExpression = "${demo.placeholders.consumer.tags}") + static class TestPlaceholdersListener implements RocketMQListener { + + @Override + public void onMessage(Object message) { + + } + } } From 79c6ae958f5dd9537dbc5b8acdbe80491bc52b0d Mon Sep 17 00:00:00 2001 From: zkzlx Date: Sun, 29 Sep 2019 18:20:05 +0800 Subject: [PATCH 021/105] RocketMQ support MessageConverter --- .../ExtProducerResetConfiguration.java | 27 ++-- .../ListenerContainerConfiguration.java | 29 +++-- .../MessageConverterConfiguration.java | 40 ++++++ .../RocketMQAutoConfiguration.java | 36 +++--- .../config/TransactionHandlerRegistry.java | 22 ++-- .../spring/core/RocketMQTemplate.java | 121 ++++++++---------- .../DefaultRocketMQListenerContainer.java | 27 +++- .../support/RocketMQMessageConverter.java | 98 ++++++++++++++ .../rocketmq/spring/support/RocketMQUtil.java | 79 +++++++++--- 9 files changed, 334 insertions(+), 145 deletions(-) create mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/MessageConverterConfiguration.java create mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index 192bfc98..45d9320e 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -17,13 +17,16 @@ package org.apache.rocketmq.spring.autoconfigure; -import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Map; +import java.util.Objects; + import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; @@ -38,8 +41,7 @@ import org.springframework.core.env.StandardEnvironment; import org.springframework.util.StringUtils; -import java.util.Map; -import java.util.Objects; +import com.fasterxml.jackson.databind.ObjectMapper; @Configuration @@ -53,14 +55,16 @@ public class ExtProducerResetConfiguration implements ApplicationContextAware, S private RocketMQProperties rocketMQProperties; private ObjectMapper objectMapper; + private RocketMQMessageConverter rocketMQMessageConverter; - public ExtProducerResetConfiguration(ObjectMapper rocketMQMessageObjectMapper, - StandardEnvironment environment, - RocketMQProperties rocketMQProperties) { - this.objectMapper = rocketMQMessageObjectMapper; - this.environment = environment; - this.rocketMQProperties = rocketMQProperties; - } + public ExtProducerResetConfiguration(ObjectMapper rocketMQMessageObjectMapper, + RocketMQMessageConverter rocketMQMessageConverter, + StandardEnvironment environment, RocketMQProperties rocketMQProperties) { + this.rocketMQMessageConverter = rocketMQMessageConverter; + this.objectMapper = rocketMQMessageObjectMapper; + this.environment = environment; + this.rocketMQProperties = rocketMQProperties; + } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { @@ -98,9 +102,8 @@ private void registerTemplate(String beanName, Object bean) { } RocketMQTemplate rocketMQTemplate = (RocketMQTemplate) bean; rocketMQTemplate.setProducer(mqProducer); + rocketMQTemplate.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); rocketMQTemplate.setObjectMapper(objectMapper); - - log.info("Set real producer to :{} {}", beanName, annotation.value()); } diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index 5d461bcf..99a98773 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -17,13 +17,18 @@ package org.apache.rocketmq.spring.autoconfigure; -import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicLong; + import org.apache.rocketmq.client.AccessChannel; 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.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; @@ -38,10 +43,7 @@ import org.springframework.core.env.StandardEnvironment; import org.springframework.util.StringUtils; -import java.util.Collections; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicLong; +import com.fasterxml.jackson.databind.ObjectMapper; @Configuration @@ -57,14 +59,16 @@ public class ListenerContainerConfiguration implements ApplicationContextAware, private RocketMQProperties rocketMQProperties; private ObjectMapper objectMapper; + private RocketMQMessageConverter rocketMQMessageConverter; - public ListenerContainerConfiguration(ObjectMapper rocketMQMessageObjectMapper, - StandardEnvironment environment, - RocketMQProperties rocketMQProperties) { - this.objectMapper = rocketMQMessageObjectMapper; - this.environment = environment; - this.rocketMQProperties = rocketMQProperties; - } + public ListenerContainerConfiguration(ObjectMapper rocketMQMessageObjectMapper, + RocketMQMessageConverter rocketMQMessageConverter, + StandardEnvironment environment, RocketMQProperties rocketMQProperties) { + this.objectMapper = rocketMQMessageObjectMapper; + this.rocketMQMessageConverter = rocketMQMessageConverter; + this.environment = environment; + this.rocketMQProperties = rocketMQProperties; + } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { @@ -139,6 +143,7 @@ private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String container.setRocketMQMessageListener(annotation); container.setRocketMQListener((RocketMQListener) bean); container.setObjectMapper(objectMapper); + container.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); container.setName(name); // REVIEW ME, use the same clientId or multiple? return container; diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/MessageConverterConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/MessageConverterConfiguration.java new file mode 100644 index 00000000..f8bf7b64 --- /dev/null +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/MessageConverterConfiguration.java @@ -0,0 +1,40 @@ +/* + * 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.autoconfigure; + +import org.apache.rocketmq.spring.support.RocketMQMessageConverter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * + * @see RocketMQMessageConverter + * + * @author zkz + */ +@Configuration +@ConditionalOnMissingBean(RocketMQMessageConverter.class) +class MessageConverterConfiguration { + + @Bean + public RocketMQMessageConverter createRocketMQMessageConverter() { + return new RocketMQMessageConverter(); + } + +} diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java index 51963698..41246e6c 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java @@ -17,7 +17,8 @@ package org.apache.rocketmq.spring.autoconfigure; -import com.fasterxml.jackson.databind.ObjectMapper; +import javax.annotation.PostConstruct; + import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.client.AccessChannel; @@ -27,6 +28,7 @@ import org.apache.rocketmq.spring.config.RocketMQTransactionAnnotationProcessor; import org.apache.rocketmq.spring.config.TransactionHandlerRegistry; import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -37,7 +39,6 @@ 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; @@ -47,14 +48,14 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import javax.annotation.PostConstruct; +import com.fasterxml.jackson.databind.ObjectMapper; @Configuration @EnableConfigurationProperties(RocketMQProperties.class) -@ConditionalOnClass({ MQAdmin.class, ObjectMapper.class }) +@ConditionalOnClass({ MQAdmin.class, ObjectMapper.class}) @ConditionalOnProperty(prefix = "rocketmq", value = "name-server", matchIfMissing = true) -@Import({ JacksonFallbackConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class }) -@AutoConfigureAfter(JacksonAutoConfiguration.class) +@Import({ JacksonFallbackConfiguration.class,MessageConverterConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class }) +@AutoConfigureAfter({JacksonFallbackConfiguration.class,MessageConverterConfiguration.class}) public class RocketMQAutoConfiguration { private static final Logger log = LoggerFactory.getLogger(RocketMQAutoConfiguration.class); @@ -113,20 +114,23 @@ public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties @Bean(destroyMethod = "destroy") @ConditionalOnBean(DefaultMQProducer.class) @ConditionalOnMissingBean(name = RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) - public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, ObjectMapper rocketMQMessageObjectMapper) { - RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); - rocketMQTemplate.setProducer(mqProducer); - rocketMQTemplate.setObjectMapper(rocketMQMessageObjectMapper); - return rocketMQTemplate; - } + public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, + ObjectMapper rocketMQMessageObjectMapper, + RocketMQMessageConverter rocketMQMessageConverter) { + RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); + rocketMQTemplate.setProducer(mqProducer); + rocketMQTemplate.setObjectMapper(rocketMQMessageObjectMapper); + rocketMQTemplate.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); + return rocketMQTemplate; + } @Bean @ConditionalOnBean(name = RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) @ConditionalOnMissingBean(TransactionHandlerRegistry.class) - public TransactionHandlerRegistry transactionHandlerRegistry(@Qualifier(RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) - RocketMQTemplate template) { - return new TransactionHandlerRegistry(template); - } + public TransactionHandlerRegistry transactionHandlerRegistry( + @Qualifier(RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) RocketMQTemplate template) { + return new TransactionHandlerRegistry(template); + } @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME) @ConditionalOnBean(TransactionHandlerRegistry.class) 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 7307a318..1809874f 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 @@ -38,15 +38,15 @@ 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(), handler.getRpcHook()); - } + 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(), handler.getRpcHook()); + } } 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 be4d1949..64c43437 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 @@ -17,8 +17,13 @@ package org.apache.rocketmq.spring.core; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; + import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.MessageQueueSelector; @@ -30,6 +35,8 @@ import org.apache.rocketmq.remoting.RPCHook; import org.apache.rocketmq.spring.config.RocketMQConfigUtils; import org.apache.rocketmq.spring.support.RocketMQUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.messaging.Message; @@ -41,14 +48,7 @@ import org.springframework.util.Assert; import org.springframework.util.MimeTypeUtils; -import java.util.ArrayList; -import java.util.Collection; -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; +import com.fasterxml.jackson.databind.ObjectMapper; @SuppressWarnings({"WeakerAccess", "unused"}) public class RocketMQTemplate extends AbstractMessageSendingTemplate implements InitializingBean, DisposableBean { @@ -56,6 +56,7 @@ public class RocketMQTemplate extends AbstractMessageSendingTemplate imp private DefaultMQProducer producer; + @Deprecated private ObjectMapper objectMapper; private String charset = "UTF-8"; @@ -71,11 +72,11 @@ public DefaultMQProducer getProducer() { public void setProducer(DefaultMQProducer producer) { this.producer = producer; } - + @Deprecated public ObjectMapper getObjectMapper() { return objectMapper; } - + @Deprecated public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } @@ -96,6 +97,7 @@ public void setMessageQueueSelector(MessageQueueSelector messageQueueSelector) { this.messageQueueSelector = messageQueueSelector; } + /** *

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 @@ -143,19 +145,19 @@ public SendResult syncSend(String destination, Collection> messages, try { long now = System.currentTimeMillis(); Collection rmqMsgs = new ArrayList<>(); - org.apache.rocketmq.common.message.Message rocketMsg; for (Message msg:messages) { if (Objects.isNull(msg) || Objects.isNull(msg.getPayload())) { log.warn("Found a message empty in the batch, skip it"); continue; } - rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper, charset, destination, msg); - rmqMsgs.add(rocketMsg); + rmqMsgs.add(this.createRocketMqMessage(destination, msg)); } SendResult sendResult = producer.send(rmqMsgs, timeout); long costTime = System.currentTimeMillis() - now; - log.debug("send messages cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); + if(log.isDebugEnabled()){ + log.debug("send messages cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); + } return sendResult; } catch (Exception e) { log.error("syncSend with batch failed. destination:{}, messages.size:{} ", destination, messages.size()); @@ -177,17 +179,17 @@ public SendResult syncSend(String destination, Message message, long timeout, 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); + org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(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()); + if(log.isDebugEnabled()){ + log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); + } return sendResult; } catch (Exception e) { log.error("syncSend failed. destination:{}, message:{} ", destination, message); @@ -215,7 +217,7 @@ public SendResult syncSend(String destination, Object payload) { * @return {@link SendResult} */ public SendResult syncSend(String destination, Object payload, long timeout) { - Message message = this.doConvert(payload, null, null); + Message message = MessageBuilder.withPayload(payload).build(); return syncSend(destination, message, timeout); } @@ -245,14 +247,14 @@ public SendResult syncSendOrderly(String destination, Message message, String 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); + org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(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()); + if(log.isDebugEnabled()){ + log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); + } return sendResult; } catch (Exception e) { log.error("syncSendOrderly failed. destination:{}, message:{} ", destination, message); @@ -282,7 +284,7 @@ public SendResult syncSendOrderly(String destination, Object payload, String has * @return {@link SendResult} */ public SendResult syncSendOrderly(String destination, Object payload, String hashKey, long timeout) { - Message message = this.doConvert(payload, null, null); + Message message = MessageBuilder.withPayload(payload).build(); return syncSendOrderly(destination, message, hashKey, timeout); } /** @@ -299,10 +301,8 @@ public void asyncSend(String destination, Message message, SendCallback sendC 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); + org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); if (delayLevel > 0) { rocketMsg.setDelayTimeLevel(delayLevel); } @@ -351,7 +351,7 @@ public void asyncSend(String destination, Message message, SendCallback sendC * @param timeout send timeout with millis */ public void asyncSend(String destination, Object payload, SendCallback sendCallback, long timeout) { - Message message = this.doConvert(payload, null, null); + Message message = MessageBuilder.withPayload(payload).build(); asyncSend(destination, message, sendCallback, timeout); } @@ -382,10 +382,8 @@ public void asyncSendOrderly(String destination, Message message, String hash 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); + org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.send(rocketMsg, messageQueueSelector, hashKey, sendCallback, timeout); } catch (Exception e) { log.error("asyncSendOrderly failed. destination:{}, message:{} ", destination, message); @@ -428,7 +426,7 @@ public void asyncSendOrderly(String destination, Object payload, String hashKey, */ public void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback, long timeout) { - Message message = this.doConvert(payload, null, null); + Message message = MessageBuilder.withPayload(payload).build(); asyncSendOrderly(destination, message, hashKey, sendCallback, timeout); } @@ -446,10 +444,8 @@ public void sendOneWay(String destination, Message message) { 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); + org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.sendOneway(rocketMsg); } catch (Exception e) { log.error("sendOneWay failed. destination:{}, message:{} ", destination, message); @@ -464,7 +460,7 @@ public void sendOneWay(String destination, Message message) { * @param payload the Object to use as payload */ public void sendOneWay(String destination, Object payload) { - Message message = this.doConvert(payload, null, null); + Message message = MessageBuilder.withPayload(payload).build(); sendOneWay(destination, message); } @@ -480,10 +476,8 @@ public void sendOneWayOrderly(String destination, Message message, String has 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); + org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.sendOneway(rocketMsg, messageQueueSelector, hashKey); } catch (Exception e) { log.error("sendOneWayOrderly failed. destination:{}, message:{}", destination, message); @@ -498,7 +492,7 @@ public void sendOneWayOrderly(String destination, Message message, String has * @param payload the Object to use as payload */ public void sendOneWayOrderly(String destination, Object payload, String hashKey) { - Message message = this.doConvert(payload, null, null); + Message message = MessageBuilder.withPayload(payload).build(); sendOneWayOrderly(destination, message, hashKey); } @@ -512,37 +506,19 @@ public void afterPropertiesSet() throws Exception { @Override protected void doSend(String destination, Message message) { SendResult sendResult = syncSend(destination, message); - log.debug("send message to `{}` finished. result:{}", destination, sendResult); + if(log.isDebugEnabled()){ + log.debug("send message to `{}` finished. result:{}", destination, sendResult); + } } @Override protected Message doConvert(Object payload, Map 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); - } + Message message = super.doConvert(payload, headers, postProcessor); + MessageBuilder builder = MessageBuilder.fromMessage(message); builder.setHeaderIfAbsent(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN); - - Message message = builder.build(); - if (postProcessor != null) { - message = postProcessor.postProcessMessage(message); - } - return message; + return builder.build(); } @Override @@ -550,7 +526,6 @@ public void destroy() { if (Objects.nonNull(producer)) { producer.shutdown(); } - for (Map.Entry kv : cache.entrySet()) { if (Objects.nonNull(kv.getValue())) { kv.getValue().shutdown(); @@ -588,8 +563,7 @@ private TransactionMQProducer stageMQProducer(String name) throws MessagingExcep 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); + org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); return txProducer.sendMessageInTransaction(rocketMsg, arg); } catch (MQClientException e) { throw RocketMQUtil.convert(e); @@ -674,4 +648,13 @@ private TransactionMQProducer createTransactionMQProducer(String name, return txProducer; } + + + private org.apache.rocketmq.common.message.Message createRocketMqMessage( + String destination, Message message) { + Message msg = this.doConvert(message.getPayload(), message.getHeaders(), null); + return RocketMQUtil.convertToRocketMessage(getMessageConverter(), charset, + destination, msg); + } + } 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 c4b5d197..c38db99b 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 @@ -17,7 +17,12 @@ package org.apache.rocketmq.spring.support; -import com.fasterxml.jackson.databind.ObjectMapper; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Objects; + import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.MessageSelector; @@ -45,13 +50,11 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.SmartLifecycle; +import org.springframework.messaging.converter.MessageConverter; +import org.springframework.messaging.support.MessageBuilder; 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; +import com.fasterxml.jackson.databind.ObjectMapper; @SuppressWarnings("WeakerAccess") public class DefaultRocketMQListenerContainer implements InitializingBean, @@ -87,6 +90,8 @@ public class DefaultRocketMQListenerContainer implements InitializingBean, private ObjectMapper objectMapper; + private MessageConverter messageConverter; + private RocketMQListener rocketMQListener; private RocketMQMessageListener rocketMQMessageListener; @@ -172,6 +177,14 @@ public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } + public MessageConverter getMessageConverter() { + return messageConverter; + } + + public DefaultRocketMQListenerContainer setMessageConverter(MessageConverter messageConverter) { + this.messageConverter = messageConverter; + return this; + } public RocketMQListener getRocketMQListener() { return rocketMQListener; @@ -376,7 +389,7 @@ private Object doConvertMessage(MessageExt messageExt) { } else { // If msgType not string, use objectMapper change it. try { - return objectMapper.readValue(str, messageType); + return messageConverter.fromMessage(MessageBuilder.withPayload(str).build(),messageType); } catch (Exception e) { log.info("convert failed. str:{}, msgType:{}", str, messageType); throw new RuntimeException("cannot convert message to " + messageType, e); diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java new file mode 100644 index 00000000..24c765b8 --- /dev/null +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java @@ -0,0 +1,98 @@ +/* + * 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 java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import org.springframework.messaging.converter.ByteArrayMessageConverter; +import org.springframework.messaging.converter.CompositeMessageConverter; +import org.springframework.messaging.converter.MappingJackson2MessageConverter; +import org.springframework.messaging.converter.MessageConverter; +import org.springframework.messaging.converter.StringMessageConverter; +import org.springframework.util.ClassUtils; + + +/** + * @see MessageConverter + * @see CompositeMessageConverter + * + * @author zkz + */ +public class RocketMQMessageConverter { + + + private static final boolean jackson2Present; + private static final boolean fastJsonPresent; + + static { + ClassLoader classLoader = RocketMQMessageConverter.class.getClassLoader(); + jackson2Present = + ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && + ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader); + fastJsonPresent = ClassUtils.isPresent("com.alibaba.fastjson.JSON",classLoader)&& + ClassUtils.isPresent("com.alibaba.fastjson.support.config.FastJsonConfig",classLoader); + } + + + + private final CompositeMessageConverter messageConverter; + + public RocketMQMessageConverter() { + List messageConverters = new ArrayList<>(); + ByteArrayMessageConverter byteArrayMessageConverter = new ByteArrayMessageConverter(); + byteArrayMessageConverter.setContentTypeResolver(null); + messageConverters.add(byteArrayMessageConverter); + messageConverters.add(new StringMessageConverter()); + if(jackson2Present) { + messageConverters.add(new MappingJackson2MessageConverter()); + } + if(fastJsonPresent){ + try { + messageConverters.add((MessageConverter) + ClassUtils.forName("com.alibaba.fastjson.support.spring.messaging.MappingFastJsonMessageConverter" + ,ClassUtils.getDefaultClassLoader()).newInstance()); + } catch (ClassNotFoundException |IllegalAccessException |InstantiationException e) { + } + } + messageConverter = new CompositeMessageConverter(messageConverters); + } + + public MessageConverter getMessageConverter() { + return messageConverter; + } + + public MessageConverter resetMessageConverter( + Collection converters) { + if (messageConverter.getConverters() != null) { + messageConverter.getConverters().clear(); + } + Objects.requireNonNull(messageConverter.getConverters()).addAll(converters); + return messageConverter; + } + + public MessageConverter addMessageConverter(MessageConverter converter) { + if (messageConverter.getConverters() != null && converter != null) { + messageConverter.getConverters().add(converter); + } + return messageConverter; + } + +} 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 index d10cb1b6..fb4d2b3b 100644 --- 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 @@ -34,6 +34,7 @@ import org.springframework.core.env.Environment; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessagingException; +import org.springframework.messaging.converter.MessageConverter; import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; @@ -127,6 +128,7 @@ public static org.springframework.messaging.Message convertToSpringMessage( return messageBuilder.build(); } + @Deprecated public static org.apache.rocketmq.common.message.Message convertToRocketMessage( ObjectMapper objectMapper, String charset, String destination, org.springframework.messaging.Message message) { @@ -145,51 +147,92 @@ public static org.apache.rocketmq.common.message.Message convertToRocketMessage( throw new RuntimeException("convert to RocketMQ message failed.", e); } } + return getAndWrapMessage(destination, message.getHeaders(), payloads); + } + public static org.apache.rocketmq.common.message.Message convertToRocketMessage( + String destination, org.springframework.messaging.Message message){ + return getAndWrapMessage(destination,message.getHeaders(),message.getPayload()); + } + private static Message getAndWrapMessage(String destination, MessageHeaders headers, byte[] payloads) { + if(destination==null || destination.length()<1){ + return null; + } + if(payloads == null || payloads.length<1){ + return null; + } 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(); + Message rocketMsg = new Message(topic, tags, payloads); 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); + if(log.isInfoEnabled()){ + 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); - + rocketMsg.setWaitStoreMsgOK(Boolean.TRUE.equals(waitStoreMsgOkObj)); headers.entrySet().stream() - .filter(entry -> !Objects.equals(entry.getKey(), "FLAG") - && !Objects.equals(entry.getKey(), "WAIT_STORE_MSG_OK")) // exclude "FLAG", "WAIT_STORE_MSG_OK" - .forEach(entry -> { - if (!MessageConst.STRING_HASH_SET.contains(entry.getKey())) { - rocketMsg.putUserProperty(entry.getKey(), String.valueOf(entry.getValue())); - } - }); + .filter(entry -> !Objects.equals(entry.getKey(), "FLAG") + && !Objects.equals(entry.getKey(), "WAIT_STORE_MSG_OK")) // exclude "FLAG", "WAIT_STORE_MSG_OK" + .forEach(entry -> { + if (!MessageConst.STRING_HASH_SET.contains(entry.getKey())) { + rocketMsg.putUserProperty(entry.getKey(), String.valueOf(entry.getValue())); + } + }); } - return rocketMsg; } + public static org.apache.rocketmq.common.message.Message convertToRocketMessage( + MessageConverter messageConverter, String charset, + String destination, org.springframework.messaging.Message message) { + Object payloadObj = message.getPayload(); + byte[] payloads; + try { + if(null == payloadObj){ + throw new RuntimeException("the message cannot be empty"); + } + if (payloadObj instanceof String) { + payloads = ((String) payloadObj).getBytes(Charset.forName(charset)); + } else if (payloadObj instanceof byte[]) { + payloads = (byte[]) message.getPayload(); + } else { + String jsonObj = (String) messageConverter.fromMessage(message, payloadObj.getClass()); + if (null == jsonObj) { + throw new RuntimeException(String.format( + "empty after conversion [messageConverter:%s,payloadClass:%s,payloadObj:%s]", + messageConverter.getClass(), payloadObj.getClass(), payloadObj)); + } + payloads = jsonObj.getBytes(Charset.forName(charset)); + } + } catch (Exception e) { + throw new RuntimeException("convert to RocketMQ message failed.", e); + } + return getAndWrapMessage(destination, message.getHeaders(), payloads); + } + + + + + + + public static RPCHook getRPCHookByAkSk(Environment env, String accessKeyOrExpr, String secretKeyOrExpr) { String ak, sk; try { From e8a1cd6abc3c77d9ac2ffc917bb7e252435f6621 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Sun, 29 Sep 2019 18:22:31 +0800 Subject: [PATCH 022/105] test --- rocketmq-spring-boot-samples/pom.xml | 2 +- .../consumer/MessageExtConsumer.java | 2 +- .../consumer/OrderPaidEventConsumer.java | 2 +- .../samples/springboot/consumer/User.java | 32 ++++++++++++ .../springboot/consumer/UserConsumer.java | 35 +++++++++++++ .../src/main/resources/application.properties | 1 + .../springboot/ProducerApplication.java | 49 ++++++++++++++++++- .../src/main/resources/application.properties | 1 + .../RocketMQAutoConfigurationTest.java | 18 +++++-- 9 files changed, 134 insertions(+), 8 deletions(-) create mode 100644 rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/User.java create mode 100644 rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java diff --git a/rocketmq-spring-boot-samples/pom.xml b/rocketmq-spring-boot-samples/pom.xml index e348e15c..c513a5d1 100644 --- a/rocketmq-spring-boot-samples/pom.xml +++ b/rocketmq-spring-boot-samples/pom.xml @@ -38,7 +38,7 @@ - 2.0.3 + 2.0.4-SNAPSHOT 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 index 59ef2630..3fa0b31a 100644 --- 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 @@ -30,7 +30,7 @@ * MessageExtConsumer, consume listener impl class. */ @Service -@RocketMQMessageListener(topic = "message-ext-topic", selectorExpression = "tag1", consumerGroup = "${spring.application.name}-message-ext-consumer") +@RocketMQMessageListener(topic = "${demo.rocketmq.msgExtTopic}", selectorExpression = "tag0||tag1", consumerGroup = "${spring.application.name}-message-ext-consumer") public class MessageExtConsumer implements RocketMQListener, RocketMQPushConsumerLifecycleListener { @Override public void onMessage(MessageExt message) { 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 677e0eab..04cb17ff 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 @@ -31,6 +31,6 @@ public class OrderPaidEventConsumer implements RocketMQListener @Override public void onMessage(OrderPaidEvent orderPaidEvent) { - System.out.printf("------- OrderPaidEventConsumer received: %s \n", orderPaidEvent); + System.out.printf("------- OrderPaidEventConsumer received: %s [orderId : %s]\n", orderPaidEvent,orderPaidEvent.getOrderId()); } } diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/User.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/User.java new file mode 100644 index 00000000..024faf2b --- /dev/null +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/User.java @@ -0,0 +1,32 @@ +package org.apache.rocketmq.samples.springboot.consumer; + +public class User{ + private String userName; + private Byte userAge; + + public String getUserName() { + return userName; + } + + public User setUserName(String userName) { + this.userName = userName; + return this; + } + + public Byte getUserAge() { + return userAge; + } + + public User setUserAge(Byte userAge) { + this.userAge = userAge; + return this; + } + + @Override + public String toString() { + return "User{" + + "userName='" + userName + '\'' + + ", userAge=" + userAge + + '}'; + } + } \ No newline at end of file diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java new file mode 100644 index 00000000..e1f4f54a --- /dev/null +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java @@ -0,0 +1,35 @@ +/* + * 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(nameServer = "${demo.rocketmq.myNameServer}",topic = "${demo.rocketmq.topic.user}", consumerGroup = "user_consumer") +public class UserConsumer implements RocketMQListener { + @Override + public void onMessage(User message) { + + System.out.printf("######## user_consumer received: %s ; age: %s ; name: %s \n", message,message.getUserAge(),message.getUserName()); + } +} 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 404cb102..583cde42 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 @@ -7,6 +7,7 @@ demo.rocketmq.topic=string-topic demo.rocketmq.orderTopic=order-paid-topic demo.rocketmq.msgExtTopic=message-ext-topic demo.rocketmq.transTopic=spring-transaction-topic +demo.rocketmq.topic.user=user-topic # another nameserver different global demo.rocketmq.myNameServer=127.0.0.1:9876 \ 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 index 8ab42e11..3a07d936 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 @@ -30,8 +30,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.MessageBuilder; +import org.springframework.util.MimeTypeUtils; import javax.annotation.Resource; import java.math.BigDecimal; @@ -52,6 +54,9 @@ public class ProducerApplication implements CommandLineRunner { private String springTransTopic; @Value("${demo.rocketmq.topic}") private String springTopic; + @Value("${demo.rocketmq.topic.user}") + private String userTopic; + @Value("${demo.rocketmq.orderTopic}") private String orderPaidTopic; @Value("${demo.rocketmq.msgExtTopic}") @@ -69,8 +74,16 @@ public void run(String... args) throws Exception { SendResult sendResult = rocketMQTemplate.syncSend(springTopic, "Hello, World!"); System.out.printf("syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); + SendResult sendResult2 = rocketMQTemplate.syncSend(userTopic, new User().setUserAge((byte) 18).setUserName("平头哥")); + System.out.printf("syncSend1 to topic %s sendResult=%s %n", userTopic, sendResult2); + + SendResult sendResult3 = rocketMQTemplate.syncSend(userTopic, MessageBuilder.withPayload( + new User().setUserAge((byte) 21).setUserName("小火箭")).setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE).build()); + System.out.printf("syncSend1 to topic %s sendResult=%s %n", userTopic, sendResult3); + + // Use the extRocketMQTemplate - sendResult = extRocketMQTemplate.syncSend(springTopic, "Hello, World!"); + sendResult = extRocketMQTemplate.syncSend(springTopic, MessageBuilder.withPayload("Hello, World!2222".getBytes()).build()); System.out.printf("extRocketMQTemplate.syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); // Send string with spring Message @@ -79,10 +92,12 @@ public void run(String... args) throws Exception { // Send user-defined object rocketMQTemplate.asyncSend(orderPaidTopic, new OrderPaidEvent("T_001", new BigDecimal("88.00")), new SendCallback() { + @Override public void onSuccess(SendResult var1) { System.out.printf("async onSucess SendResult=%s %n", var1); } + @Override public void onException(Throwable var1) { System.out.printf("async onException Throwable=%s %n", var1); } @@ -192,4 +207,36 @@ public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { } } + class User{ + private String userName; + private Byte userAge; + + public String getUserName() { + return userName; + } + + public User setUserName(String userName) { + this.userName = userName; + return this; + } + + public Byte getUserAge() { + return userAge; + } + + public User setUserAge(Byte userAge) { + this.userAge = userAge; + return this; + } + + @Override + public String toString() { + return "User{" + + "userName='" + userName + '\'' + + ", userAge=" + userAge + + '}'; + } + } + + } 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 3a685051..27a3abc2 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 @@ -7,5 +7,6 @@ demo.rocketmq.topic=string-topic demo.rocketmq.orderTopic=order-paid-topic demo.rocketmq.msgExtTopic=message-ext-topic demo.rocketmq.transTopic=spring-transaction-topic +demo.rocketmq.topic.user=user-topic demo.rocketmq.extNameServer=127.0.0.1:9876 \ No newline at end of file diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index 18fdcca0..ed17ab9e 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -27,6 +27,7 @@ import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer; +import org.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.junit.Assert; import org.junit.Test; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -110,8 +111,8 @@ public void testRocketMQListenerWithCustomObjectMapper() { withUserConfiguration(TestConfig.class, CustomObjectMapperConfig.class). run((context) -> { assertThat(context.getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1", - DefaultRocketMQListenerContainer.class).getObjectMapper()) - .isSameAs(context.getBean(CustomObjectMapperConfig.class).testObjectMapper()); + DefaultRocketMQListenerContainer.class).getMessageConverter()) + .isSameAs(context.getBean(CustomObjectMapperConfig.class).rocketMQMessageConverter().getMessageConverter()); }); } @@ -121,8 +122,8 @@ public void testRocketMQListenerWithSeveralObjectMappers() { withUserConfiguration(TestConfig.class, CustomObjectMappersConfig.class). run((context) -> { assertThat(context.getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1", - DefaultRocketMQListenerContainer.class).getObjectMapper()) - .isSameAs(context.getBean(CustomObjectMappersConfig.class).rocketMQMessageObjectMapper()); + DefaultRocketMQListenerContainer.class).getMessageConverter()) + .isSameAs(context.getBean(CustomObjectMappersConfig.class).rocketMQMessageConverter().getMessageConverter()); }); } @@ -198,6 +199,11 @@ static class CustomObjectMapperConfig { public ObjectMapper testObjectMapper() { return new ObjectMapper(); } + @Bean + public RocketMQMessageConverter rocketMQMessageConverter() { + return new RocketMQMessageConverter(); + } + } @@ -213,6 +219,10 @@ public ObjectMapper testObjectMapper() { public ObjectMapper rocketMQMessageObjectMapper() { return new ObjectMapper(); } + @Bean + public RocketMQMessageConverter rocketMQMessageConverter() { + return new RocketMQMessageConverter(); + } } From 4c623e73a568ff4f4f25e5b1f9b76c6b8dd88eea Mon Sep 17 00:00:00 2001 From: zkzlx Date: Mon, 30 Sep 2019 14:04:50 +0800 Subject: [PATCH 023/105] rocketmq-format-style --- .../ExtProducerResetConfiguration.java | 46 +++---- .../ListenerContainerConfiguration.java | 29 ++--- .../MessageConverterConfiguration.java | 11 +- .../RocketMQAutoConfiguration.java | 36 +++--- .../config/TransactionHandlerRegistry.java | 22 ++-- .../spring/core/RocketMQTemplate.java | 97 ++++++++------- .../support/RocketMQMessageConverter.java | 114 +++++++++--------- .../rocketmq/spring/support/RocketMQUtil.java | 81 +++++++------ 8 files changed, 225 insertions(+), 211 deletions(-) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index 45d9320e..8bf061b3 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -43,7 +43,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; - @Configuration public class ExtProducerResetConfiguration implements ApplicationContextAware, SmartInitializingSingleton { private final static Logger log = LoggerFactory.getLogger(ExtProducerResetConfiguration.class); @@ -57,18 +56,18 @@ public class ExtProducerResetConfiguration implements ApplicationContextAware, S private ObjectMapper objectMapper; private RocketMQMessageConverter rocketMQMessageConverter; - public ExtProducerResetConfiguration(ObjectMapper rocketMQMessageObjectMapper, - RocketMQMessageConverter rocketMQMessageConverter, - StandardEnvironment environment, RocketMQProperties rocketMQProperties) { - this.rocketMQMessageConverter = rocketMQMessageConverter; - this.objectMapper = rocketMQMessageObjectMapper; - this.environment = environment; - this.rocketMQProperties = rocketMQProperties; - } + public ExtProducerResetConfiguration(ObjectMapper rocketMQMessageObjectMapper, + RocketMQMessageConverter rocketMQMessageConverter, + StandardEnvironment environment, RocketMQProperties rocketMQProperties) { + this.rocketMQMessageConverter = rocketMQMessageConverter; + this.objectMapper = rocketMQMessageObjectMapper; + this.environment = environment; + this.rocketMQProperties = rocketMQProperties; + } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = (ConfigurableApplicationContext) applicationContext; + this.applicationContext = (ConfigurableApplicationContext)applicationContext; } @Override @@ -88,7 +87,7 @@ private void registerTemplate(String beanName, Object bean) { } ExtRocketMQTemplateConfiguration annotation = clazz.getAnnotation(ExtRocketMQTemplateConfiguration.class); - GenericApplicationContext genericApplicationContext = (GenericApplicationContext) applicationContext; + GenericApplicationContext genericApplicationContext = (GenericApplicationContext)applicationContext; validate(annotation, genericApplicationContext); DefaultMQProducer mqProducer = createProducer(annotation); @@ -96,11 +95,12 @@ private void registerTemplate(String beanName, Object bean) { mqProducer.setInstanceName(beanName); try { mqProducer.start(); - } catch (MQClientException e) { + } + catch (MQClientException e) { throw new BeanDefinitionValidationException(String.format("Failed to startup MQProducer for RocketMQTemplate {}", - beanName), e); + beanName), e); } - RocketMQTemplate rocketMQTemplate = (RocketMQTemplate) bean; + RocketMQTemplate rocketMQTemplate = (RocketMQTemplate)bean; rocketMQTemplate.setProducer(mqProducer); rocketMQTemplate.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); rocketMQTemplate.setObjectMapper(objectMapper); @@ -127,9 +127,10 @@ private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annota if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { producer = new DefaultMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk)), - annotation.enableMsgTrace(), customizedTraceTopic); + annotation.enableMsgTrace(), customizedTraceTopic); producer.setVipChannelEnabled(false); - } else { + } + else { producer = new DefaultMQProducer(groupName, annotation.enableMsgTrace(), customizedTraceTopic); } @@ -144,18 +145,19 @@ private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annota return producer; } - private void validate(ExtRocketMQTemplateConfiguration annotation, GenericApplicationContext genericApplicationContext) { + private void validate(ExtRocketMQTemplateConfiguration annotation, + GenericApplicationContext genericApplicationContext) { if (genericApplicationContext.isBeanNameInUse(annotation.value())) { throw new BeanDefinitionValidationException(String.format("Bean {} has been used in Spring Application Context, " + - "please check the @ExtRocketMQTemplateConfiguration", - annotation.value())); + "please check the @ExtRocketMQTemplateConfiguration", + annotation.value())); } if (rocketMQProperties.getNameServer() == null || - rocketMQProperties.getNameServer().equals(environment.resolvePlaceholders(annotation.nameServer()))) { + rocketMQProperties.getNameServer().equals(environment.resolvePlaceholders(annotation.nameServer()))) { throw new BeanDefinitionValidationException( - "Bad annotation definition in @ExtRocketMQTemplateConfiguration, nameServer property is same with " + - "global property, please use the default RocketMQTemplate!"); + "Bad annotation definition in @ExtRocketMQTemplateConfiguration, nameServer property is same with " + + "global property, please use the default RocketMQTemplate!"); } } } \ No newline at end of file diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index 99a98773..82d90d23 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -45,7 +45,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; - @Configuration public class ListenerContainerConfiguration implements ApplicationContextAware, SmartInitializingSingleton { private final static Logger log = LoggerFactory.getLogger(ListenerContainerConfiguration.class); @@ -61,18 +60,18 @@ public class ListenerContainerConfiguration implements ApplicationContextAware, private ObjectMapper objectMapper; private RocketMQMessageConverter rocketMQMessageConverter; - public ListenerContainerConfiguration(ObjectMapper rocketMQMessageObjectMapper, - RocketMQMessageConverter rocketMQMessageConverter, - StandardEnvironment environment, RocketMQProperties rocketMQProperties) { - this.objectMapper = rocketMQMessageObjectMapper; - this.rocketMQMessageConverter = rocketMQMessageConverter; - this.environment = environment; - this.rocketMQProperties = rocketMQProperties; - } + public ListenerContainerConfiguration(ObjectMapper rocketMQMessageObjectMapper, + RocketMQMessageConverter rocketMQMessageConverter, + StandardEnvironment environment, RocketMQProperties rocketMQProperties) { + this.objectMapper = rocketMQMessageObjectMapper; + this.rocketMQMessageConverter = rocketMQMessageConverter; + this.environment = environment; + this.rocketMQProperties = rocketMQProperties; + } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = (ConfigurableApplicationContext) applicationContext; + this.applicationContext = (ConfigurableApplicationContext)applicationContext; } @Override @@ -110,7 +109,7 @@ private void registerContainer(String beanName, Object bean) { String containerBeanName = String.format("%s_%s", DefaultRocketMQListenerContainer.class.getName(), counter.incrementAndGet()); - GenericApplicationContext genericApplicationContext = (GenericApplicationContext) applicationContext; + GenericApplicationContext genericApplicationContext = (GenericApplicationContext)applicationContext; genericApplicationContext.registerBean(containerBeanName, DefaultRocketMQListenerContainer.class, () -> createRocketMQListenerContainer(containerBeanName, bean, annotation)); @@ -119,7 +118,8 @@ private void registerContainer(String beanName, Object bean) { if (!container.isRunning()) { try { container.start(); - } catch (Exception e) { + } + catch (Exception e) { log.error("Started container failed. {}", container, e); throw new RuntimeException(e); } @@ -128,7 +128,8 @@ private void registerContainer(String beanName, Object bean) { log.info("Register the listener to container, listenerBeanName:{}, containerBeanName:{}", beanName, containerBeanName); } - private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String name, Object bean, RocketMQMessageListener annotation) { + private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String name, Object bean, + RocketMQMessageListener annotation) { DefaultRocketMQListenerContainer container = new DefaultRocketMQListenerContainer(); String nameServer = environment.resolvePlaceholders(annotation.nameServer()); @@ -141,7 +142,7 @@ private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String container.setTopic(environment.resolvePlaceholders(annotation.topic())); container.setConsumerGroup(environment.resolvePlaceholders(annotation.consumerGroup())); container.setRocketMQMessageListener(annotation); - container.setRocketMQListener((RocketMQListener) bean); + container.setRocketMQListener((RocketMQListener)bean); container.setObjectMapper(objectMapper); container.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); container.setName(name); // REVIEW ME, use the same clientId or multiple? diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/MessageConverterConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/MessageConverterConfiguration.java index f8bf7b64..5f7e4194 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/MessageConverterConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/MessageConverterConfiguration.java @@ -23,18 +23,15 @@ import org.springframework.context.annotation.Configuration; /** - * * @see RocketMQMessageConverter - * - * @author zkz */ @Configuration @ConditionalOnMissingBean(RocketMQMessageConverter.class) class MessageConverterConfiguration { - @Bean - public RocketMQMessageConverter createRocketMQMessageConverter() { - return new RocketMQMessageConverter(); - } + @Bean + public RocketMQMessageConverter createRocketMQMessageConverter() { + return new RocketMQMessageConverter(); + } } diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java index 41246e6c..91b26096 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java @@ -52,10 +52,10 @@ @Configuration @EnableConfigurationProperties(RocketMQProperties.class) -@ConditionalOnClass({ MQAdmin.class, ObjectMapper.class}) +@ConditionalOnClass({MQAdmin.class, ObjectMapper.class}) @ConditionalOnProperty(prefix = "rocketmq", value = "name-server", matchIfMissing = true) -@Import({ JacksonFallbackConfiguration.class,MessageConverterConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class }) -@AutoConfigureAfter({JacksonFallbackConfiguration.class,MessageConverterConfiguration.class}) +@Import({JacksonFallbackConfiguration.class, MessageConverterConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class}) +@AutoConfigureAfter({JacksonFallbackConfiguration.class, MessageConverterConfiguration.class}) public class RocketMQAutoConfiguration { private static final Logger log = LoggerFactory.getLogger(RocketMQAutoConfiguration.class); @@ -71,7 +71,6 @@ public void checkProperties() { } } - @Bean @ConditionalOnMissingBean(DefaultMQProducer.class) @ConditionalOnProperty(prefix = "rocketmq", value = {"name-server", "producer.group"}) @@ -92,7 +91,8 @@ public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties rocketMQProperties.getProducer().isEnableMsgTrace(), rocketMQProperties.getProducer().getCustomizedTraceTopic()); producer.setVipChannelEnabled(false); - } else { + } + else { producer = new DefaultMQProducer(groupName, rocketMQProperties.getProducer().isEnableMsgTrace(), rocketMQProperties.getProducer().getCustomizedTraceTopic()); } @@ -114,23 +114,23 @@ public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties @Bean(destroyMethod = "destroy") @ConditionalOnBean(DefaultMQProducer.class) @ConditionalOnMissingBean(name = RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) - public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, - ObjectMapper rocketMQMessageObjectMapper, - RocketMQMessageConverter rocketMQMessageConverter) { - RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); - rocketMQTemplate.setProducer(mqProducer); - rocketMQTemplate.setObjectMapper(rocketMQMessageObjectMapper); - rocketMQTemplate.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); - return rocketMQTemplate; - } + public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, + ObjectMapper rocketMQMessageObjectMapper, + RocketMQMessageConverter rocketMQMessageConverter) { + RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); + rocketMQTemplate.setProducer(mqProducer); + rocketMQTemplate.setObjectMapper(rocketMQMessageObjectMapper); + rocketMQTemplate.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); + return rocketMQTemplate; + } @Bean @ConditionalOnBean(name = RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) @ConditionalOnMissingBean(TransactionHandlerRegistry.class) - public TransactionHandlerRegistry transactionHandlerRegistry( - @Qualifier(RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) RocketMQTemplate template) { - return new TransactionHandlerRegistry(template); - } + public TransactionHandlerRegistry transactionHandlerRegistry( + @Qualifier(RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) RocketMQTemplate template) { + return new TransactionHandlerRegistry(template); + } @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME) @ConditionalOnBean(TransactionHandlerRegistry.class) 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 1809874f..0ec01615 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 @@ -38,15 +38,15 @@ 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(), handler.getRpcHook()); - } + 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(), handler.getRpcHook()); + } } 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 64c43437..51f442ad 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 @@ -52,7 +52,7 @@ @SuppressWarnings({"WeakerAccess", "unused"}) public class RocketMQTemplate extends AbstractMessageSendingTemplate implements InitializingBean, DisposableBean { - private static final Logger log = LoggerFactory.getLogger(RocketMQTemplate.class); + private static final Logger log = LoggerFactory.getLogger(RocketMQTemplate.class); private DefaultMQProducer producer; @@ -72,10 +72,12 @@ public DefaultMQProducer getProducer() { public void setProducer(DefaultMQProducer producer) { this.producer = producer; } + @Deprecated public ObjectMapper getObjectMapper() { return objectMapper; } + @Deprecated public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; @@ -97,7 +99,6 @@ public void setMessageQueueSelector(MessageQueueSelector messageQueueSelector) { this.messageQueueSelector = messageQueueSelector; } - /** *

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 @@ -145,7 +146,7 @@ public SendResult syncSend(String destination, Collection> messages, try { long now = System.currentTimeMillis(); Collection rmqMsgs = new ArrayList<>(); - for (Message msg:messages) { + for (Message msg : messages) { if (Objects.isNull(msg) || Objects.isNull(msg.getPayload())) { log.warn("Found a message empty in the batch, skip it"); continue; @@ -155,11 +156,12 @@ public SendResult syncSend(String destination, Collection> messages, SendResult sendResult = producer.send(rmqMsgs, timeout); long costTime = System.currentTimeMillis() - now; - if(log.isDebugEnabled()){ + if (log.isDebugEnabled()) { log.debug("send messages cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } catch (Exception e) { + } + catch (Exception e) { log.error("syncSend with batch failed. destination:{}, messages.size:{} ", destination, messages.size()); throw new MessagingException(e.getMessage(), e); } @@ -187,11 +189,12 @@ public SendResult syncSend(String destination, Message message, long timeout, } SendResult sendResult = producer.send(rocketMsg, timeout); long costTime = System.currentTimeMillis() - now; - if(log.isDebugEnabled()){ + if (log.isDebugEnabled()) { log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } catch (Exception e) { + } + catch (Exception e) { log.error("syncSend failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -252,11 +255,12 @@ public SendResult syncSendOrderly(String destination, Message message, String org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); SendResult sendResult = producer.send(rocketMsg, messageQueueSelector, hashKey, timeout); long costTime = System.currentTimeMillis() - now; - if(log.isDebugEnabled()){ + if (log.isDebugEnabled()) { log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } catch (Exception e) { + } + catch (Exception e) { log.error("syncSendOrderly failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -287,8 +291,10 @@ public SendResult syncSendOrderly(String destination, Object payload, String has Message message = MessageBuilder.withPayload(payload).build(); return syncSendOrderly(destination, message, hashKey, timeout); } + /** - * Same to {@link #asyncSend(String, Message, SendCallback)} with send timeout and delay level specified in addition. + * Same to {@link #asyncSend(String, Message, SendCallback)} with send timeout and delay level specified in + * addition. * * @param destination formats: `topicName:tags` * @param message {@link org.springframework.messaging.Message} @@ -296,7 +302,8 @@ public SendResult syncSendOrderly(String destination, Object payload, String has * @param timeout send timeout with millis * @param delayLevel level for the delay message */ - public void asyncSend(String destination, Message message, SendCallback sendCallback, long timeout, int delayLevel) { + public void asyncSend(String destination, Message message, SendCallback sendCallback, long timeout, + int delayLevel) { 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"); @@ -307,11 +314,13 @@ public void asyncSend(String destination, Message message, SendCallback sendC rocketMsg.setDelayTimeLevel(delayLevel); } producer.send(rocketMsg, sendCallback, timeout); - } catch (Exception e) { + } + catch (Exception e) { log.info("asyncSend failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } } + /** * Same to {@link #asyncSend(String, Message, SendCallback)} with send timeout specified in addition. * @@ -321,11 +330,12 @@ public void asyncSend(String destination, Message message, SendCallback sendC * @param timeout send timeout with millis */ public void asyncSend(String destination, Message message, SendCallback sendCallback, long timeout) { - asyncSend(destination,message,sendCallback,timeout,0); + asyncSend(destination, message, sendCallback, timeout, 0); } /** - *

Send message to broker asynchronously. asynchronous transmission is generally used in response time sensitive + *

Send message to broker asynchronously. asynchronous transmission is generally used in response time + * sensitive * business scenarios.

*

* This method returns immediately. On sending completion, sendCallback will be executed. @@ -377,7 +387,7 @@ public void asyncSend(String destination, Object payload, SendCallback sendCallb * @param timeout send timeout with millis */ public void asyncSendOrderly(String destination, Message message, String hashKey, SendCallback sendCallback, - long timeout) { + 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"); @@ -385,7 +395,8 @@ public void asyncSendOrderly(String destination, Message message, String hash try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.send(rocketMsg, messageQueueSelector, hashKey, sendCallback, timeout); - } catch (Exception e) { + } + catch (Exception e) { log.error("asyncSendOrderly failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -425,7 +436,7 @@ public void asyncSendOrderly(String destination, Object payload, String hashKey, * @param timeout send timeout with millis */ public void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback, - long timeout) { + long timeout) { Message message = MessageBuilder.withPayload(payload).build(); asyncSendOrderly(destination, message, hashKey, sendCallback, timeout); } @@ -447,7 +458,8 @@ public void sendOneWay(String destination, Message message) { try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.sendOneway(rocketMsg); - } catch (Exception e) { + } + catch (Exception e) { log.error("sendOneWay failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -479,7 +491,8 @@ public void sendOneWayOrderly(String destination, Message message, String has try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.sendOneway(rocketMsg, messageQueueSelector, hashKey); - } catch (Exception e) { + } + catch (Exception e) { log.error("sendOneWayOrderly failed. destination:{}, message:{}", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -506,13 +519,11 @@ public void afterPropertiesSet() throws Exception { @Override protected void doSend(String destination, Message message) { SendResult sendResult = syncSend(destination, message); - if(log.isDebugEnabled()){ + if (log.isDebugEnabled()) { log.debug("send message to `{}` finished. result:{}", destination, sendResult); } } - - @Override protected Message doConvert(Object payload, Map headers, MessagePostProcessor postProcessor) { Message message = super.doConvert(payload, headers, postProcessor); @@ -560,19 +571,22 @@ private TransactionMQProducer stageMQProducer(String name) throws MessagingExcep * @return TransactionSendResult * @throws MessagingException */ - public TransactionSendResult sendMessageInTransaction(final String txProducerGroup, final String destination, final Message message, final Object arg) 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 = this.createRocketMqMessage(destination, message); return txProducer.sendMessageInTransaction(rocketMsg, arg); - } catch (MQClientException e) { + } + catch (MQClientException e) { throw RocketMQUtil.convert(e); } } /** * Remove a TransactionMQProducer from cache by manual. - *

Note: RocketMQTemplate can release all cached producers when bean destroying, it is not recommended to directly + *

Note: RocketMQTemplate can release all cached producers when bean destroying, it is not recommended to + * directly * use this method by user. * * @param txProducerGroup @@ -595,13 +609,13 @@ public void removeTransactionMQProducer(String txProducerGroup) throws Messaging * @param txProducerGroup Producer (group) name, unique for each producer * @param transactionListener TransactoinListener impl class * @param executorService Nullable. - * @param rpcHook Nullable. + * @param rpcHook 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, RPCHook rpcHook) throws MessagingException { + RocketMQLocalTransactionListener transactionListener, + ExecutorService executorService, RPCHook rpcHook) throws MessagingException { txProducerGroup = getTxProducerGroupName(txProducerGroup); if (cache.containsKey(txProducerGroup)) { log.info(String.format("get TransactionMQProducer '%s' from cache", txProducerGroup)); @@ -612,7 +626,8 @@ public boolean createAndStartTransactionMQProducer(String txProducerGroup, try { txProducer.start(); cache.put(txProducerGroup, txProducer); - } catch (MQClientException e) { + } + catch (MQClientException e) { throw RocketMQUtil.convert(e); } @@ -620,8 +635,8 @@ public boolean createAndStartTransactionMQProducer(String txProducerGroup, } private TransactionMQProducer createTransactionMQProducer(String name, - RocketMQLocalTransactionListener transactionListener, - ExecutorService executorService, RPCHook rpcHook) { + RocketMQLocalTransactionListener transactionListener, + ExecutorService executorService, RPCHook rpcHook) { Assert.notNull(producer, "Property 'producer' is required"); Assert.notNull(transactionListener, "Parameter 'transactionListener' is required"); TransactionMQProducer txProducer; @@ -629,7 +644,8 @@ private TransactionMQProducer createTransactionMQProducer(String name, txProducer = new TransactionMQProducer(name, rpcHook); txProducer.setVipChannelEnabled(false); txProducer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, name)); - } else { + } + else { txProducer = new TransactionMQProducer(name); } txProducer.setTransactionListener(RocketMQUtil.convert(transactionListener)); @@ -648,13 +664,12 @@ private TransactionMQProducer createTransactionMQProducer(String name, return txProducer; } - - - private org.apache.rocketmq.common.message.Message createRocketMqMessage( - String destination, Message message) { - Message msg = this.doConvert(message.getPayload(), message.getHeaders(), null); - return RocketMQUtil.convertToRocketMessage(getMessageConverter(), charset, - destination, msg); - } - + + private org.apache.rocketmq.common.message.Message createRocketMqMessage( + String destination, Message message) { + Message msg = this.doConvert(message.getPayload(), message.getHeaders(), null); + return RocketMQUtil.convertToRocketMessage(getMessageConverter(), charset, + destination, msg); + } + } diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java index 24c765b8..f8dbee95 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java @@ -29,70 +29,66 @@ import org.springframework.messaging.converter.StringMessageConverter; import org.springframework.util.ClassUtils; - /** * @see MessageConverter * @see CompositeMessageConverter - * - * @author zkz */ public class RocketMQMessageConverter { - - private static final boolean jackson2Present; - private static final boolean fastJsonPresent; - - static { - ClassLoader classLoader = RocketMQMessageConverter.class.getClassLoader(); - jackson2Present = - ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && - ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader); - fastJsonPresent = ClassUtils.isPresent("com.alibaba.fastjson.JSON",classLoader)&& - ClassUtils.isPresent("com.alibaba.fastjson.support.config.FastJsonConfig",classLoader); - } - - - - private final CompositeMessageConverter messageConverter; - - public RocketMQMessageConverter() { - List messageConverters = new ArrayList<>(); - ByteArrayMessageConverter byteArrayMessageConverter = new ByteArrayMessageConverter(); - byteArrayMessageConverter.setContentTypeResolver(null); - messageConverters.add(byteArrayMessageConverter); - messageConverters.add(new StringMessageConverter()); - if(jackson2Present) { - messageConverters.add(new MappingJackson2MessageConverter()); - } - if(fastJsonPresent){ - try { - messageConverters.add((MessageConverter) - ClassUtils.forName("com.alibaba.fastjson.support.spring.messaging.MappingFastJsonMessageConverter" - ,ClassUtils.getDefaultClassLoader()).newInstance()); - } catch (ClassNotFoundException |IllegalAccessException |InstantiationException e) { - } - } - messageConverter = new CompositeMessageConverter(messageConverters); - } - - public MessageConverter getMessageConverter() { - return messageConverter; - } - - public MessageConverter resetMessageConverter( - Collection converters) { - if (messageConverter.getConverters() != null) { - messageConverter.getConverters().clear(); - } - Objects.requireNonNull(messageConverter.getConverters()).addAll(converters); - return messageConverter; - } - - public MessageConverter addMessageConverter(MessageConverter converter) { - if (messageConverter.getConverters() != null && converter != null) { - messageConverter.getConverters().add(converter); - } - return messageConverter; - } + private static final boolean JACKSON_PRESENT; + private static final boolean FASTJSON_PRESENT; + + static { + ClassLoader classLoader = RocketMQMessageConverter.class.getClassLoader(); + JACKSON_PRESENT = + ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) && + ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader); + FASTJSON_PRESENT = ClassUtils.isPresent("com.alibaba.fastjson.JSON", classLoader) && + ClassUtils.isPresent("com.alibaba.fastjson.support.config.FastJsonConfig", classLoader); + } + + private final CompositeMessageConverter messageConverter; + + public RocketMQMessageConverter() { + List messageConverters = new ArrayList<>(); + ByteArrayMessageConverter byteArrayMessageConverter = new ByteArrayMessageConverter(); + byteArrayMessageConverter.setContentTypeResolver(null); + messageConverters.add(byteArrayMessageConverter); + messageConverters.add(new StringMessageConverter()); + if (JACKSON_PRESENT) { + messageConverters.add(new MappingJackson2MessageConverter()); + } + if (FASTJSON_PRESENT) { + try { + messageConverters.add( + (MessageConverter)ClassUtils.forName( + "com.alibaba.fastjson.support.spring.messaging.MappingFastJsonMessageConverter", + ClassUtils.getDefaultClassLoader()).newInstance()); + } + catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { + } + } + messageConverter = new CompositeMessageConverter(messageConverters); + } + + public MessageConverter getMessageConverter() { + return messageConverter; + } + + public MessageConverter resetMessageConverter( + Collection converters) { + if (messageConverter.getConverters() != null) { + messageConverter.getConverters().clear(); + } + Objects.requireNonNull(messageConverter.getConverters()).addAll(converters); + return messageConverter; + } + + public MessageConverter addMessageConverter(MessageConverter converter) { + if (messageConverter.getConverters() != null && converter != null) { + messageConverter.getConverters().add(converter); + } + return messageConverter; + } } 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 index fb4d2b3b..720486de 100644 --- 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 @@ -107,8 +107,8 @@ private static void addUserProperties(Map properties, MessageBui if (!CollectionUtils.isEmpty(properties)) { properties.forEach((key, val) -> { if (!MessageConst.STRING_HASH_SET.contains(key) && !MessageHeaders.ID.equals(key) - && !MessageHeaders.TIMESTAMP.equals(key) && - (!key.startsWith(RocketMQHeaders.PREFIX) || !MessageConst.STRING_HASH_SET.contains(key.replaceFirst("^" + RocketMQHeaders.PREFIX, "")))) { + && !MessageHeaders.TIMESTAMP.equals(key) && + (!key.startsWith(RocketMQHeaders.PREFIX) || !MessageConst.STRING_HASH_SET.contains(key.replaceFirst("^" + RocketMQHeaders.PREFIX, "")))) { messageBuilder.setHeader(key, val); } }); @@ -136,14 +136,17 @@ public static org.apache.rocketmq.common.message.Message convertToRocketMessage( byte[] payloads; if (payloadObj instanceof String) { - payloads = ((String) payloadObj).getBytes(Charset.forName(charset)); - } else if (payloadObj instanceof byte[]) { - payloads = (byte[]) message.getPayload(); - } else { + payloads = ((String)payloadObj).getBytes(Charset.forName(charset)); + } + else if (payloadObj instanceof byte[]) { + payloads = (byte[])message.getPayload(); + } + else { try { String jsonObj = objectMapper.writeValueAsString(payloadObj); payloads = jsonObj.getBytes(Charset.forName(charset)); - } catch (Exception e) { + } + catch (Exception e) { throw new RuntimeException("convert to RocketMQ message failed.", e); } } @@ -151,14 +154,15 @@ public static org.apache.rocketmq.common.message.Message convertToRocketMessage( } public static org.apache.rocketmq.common.message.Message convertToRocketMessage( - String destination, org.springframework.messaging.Message message){ - return getAndWrapMessage(destination,message.getHeaders(),message.getPayload()); + String destination, org.springframework.messaging.Message message) { + return getAndWrapMessage(destination, message.getHeaders(), message.getPayload()); } + private static Message getAndWrapMessage(String destination, MessageHeaders headers, byte[] payloads) { - if(destination==null || destination.length()<1){ + if (destination == null || destination.length() < 1) { return null; } - if(payloads == null || payloads.length<1){ + if (payloads == null || payloads.length < 1) { return null; } String[] tempArr = destination.split(":", 2); @@ -177,9 +181,10 @@ private static Message getAndWrapMessage(String destination, MessageHeaders head int flag = 0; try { flag = Integer.parseInt(flagObj.toString()); - } catch (NumberFormatException e) { + } + catch (NumberFormatException e) { // Ignore it - if(log.isInfoEnabled()){ + if (log.isInfoEnabled()) { log.info("flag must be integer, flagObj:{}", flagObj); } } @@ -187,58 +192,56 @@ private static Message getAndWrapMessage(String destination, MessageHeaders head Object waitStoreMsgOkObj = headers.getOrDefault("WAIT_STORE_MSG_OK", "true"); rocketMsg.setWaitStoreMsgOK(Boolean.TRUE.equals(waitStoreMsgOkObj)); headers.entrySet().stream() - .filter(entry -> !Objects.equals(entry.getKey(), "FLAG") - && !Objects.equals(entry.getKey(), "WAIT_STORE_MSG_OK")) // exclude "FLAG", "WAIT_STORE_MSG_OK" - .forEach(entry -> { - if (!MessageConst.STRING_HASH_SET.contains(entry.getKey())) { - rocketMsg.putUserProperty(entry.getKey(), String.valueOf(entry.getValue())); - } - }); + .filter(entry -> !Objects.equals(entry.getKey(), "FLAG") + && !Objects.equals(entry.getKey(), "WAIT_STORE_MSG_OK")) // exclude "FLAG", "WAIT_STORE_MSG_OK" + .forEach(entry -> { + if (!MessageConst.STRING_HASH_SET.contains(entry.getKey())) { + rocketMsg.putUserProperty(entry.getKey(), String.valueOf(entry.getValue())); + } + }); } return rocketMsg; } public static org.apache.rocketmq.common.message.Message convertToRocketMessage( - MessageConverter messageConverter, String charset, - String destination, org.springframework.messaging.Message message) { + MessageConverter messageConverter, String charset, + String destination, org.springframework.messaging.Message message) { Object payloadObj = message.getPayload(); byte[] payloads; try { - if(null == payloadObj){ + if (null == payloadObj) { throw new RuntimeException("the message cannot be empty"); } if (payloadObj instanceof String) { - payloads = ((String) payloadObj).getBytes(Charset.forName(charset)); - } else if (payloadObj instanceof byte[]) { - payloads = (byte[]) message.getPayload(); - } else { - String jsonObj = (String) messageConverter.fromMessage(message, payloadObj.getClass()); + payloads = ((String)payloadObj).getBytes(Charset.forName(charset)); + } + else if (payloadObj instanceof byte[]) { + payloads = (byte[])message.getPayload(); + } + else { + String jsonObj = (String)messageConverter.fromMessage(message, payloadObj.getClass()); if (null == jsonObj) { throw new RuntimeException(String.format( - "empty after conversion [messageConverter:%s,payloadClass:%s,payloadObj:%s]", - messageConverter.getClass(), payloadObj.getClass(), payloadObj)); + "empty after conversion [messageConverter:%s,payloadClass:%s,payloadObj:%s]", + messageConverter.getClass(), payloadObj.getClass(), payloadObj)); } payloads = jsonObj.getBytes(Charset.forName(charset)); } - } catch (Exception e) { + } + catch (Exception e) { throw new RuntimeException("convert to RocketMQ message failed.", e); } return getAndWrapMessage(destination, message.getHeaders(), payloads); } - - - - - - public static RPCHook getRPCHookByAkSk(Environment env, String accessKeyOrExpr, String secretKeyOrExpr) { String ak, sk; try { ak = env.resolveRequiredPlaceholders(accessKeyOrExpr); sk = env.resolveRequiredPlaceholders(secretKeyOrExpr); - } catch (Exception e) { + } + catch (Exception e) { // Ignore it ak = null; sk = null; @@ -252,7 +255,7 @@ public static RPCHook getRPCHookByAkSk(Environment env, String accessKeyOrExpr, public static String getInstanceName(RPCHook rpcHook, String identify) { String separator = "|"; StringBuilder instanceName = new StringBuilder(); - SessionCredentials sessionCredentials = ((AclClientRPCHook) rpcHook).getSessionCredentials(); + SessionCredentials sessionCredentials = ((AclClientRPCHook)rpcHook).getSessionCredentials(); instanceName.append(sessionCredentials.getAccessKey()) .append(separator).append(sessionCredentials.getSecretKey()) .append(separator).append(identify) From bd855b7eb91d6dc569f8d550e7708048e4785b8a Mon Sep 17 00:00:00 2001 From: zkzlx Date: Mon, 30 Sep 2019 15:27:46 +0800 Subject: [PATCH 024/105] resolve Travis CI build --- .../samples/springboot/consumer/User.java | 67 ++++++++++++------- .../springboot/consumer/UserConsumer.java | 4 +- .../springboot/ProducerApplication.java | 23 +++---- 3 files changed, 54 insertions(+), 40 deletions(-) diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/User.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/User.java index 024faf2b..e020fc27 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/User.java +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/User.java @@ -1,32 +1,49 @@ +/* + * 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; -public class User{ - private String userName; - private Byte userAge; +public class User { + private String userName; + private Byte userAge; - public String getUserName() { - return userName; - } + public String getUserName() { + return userName; + } - public User setUserName(String userName) { - this.userName = userName; - return this; - } + public User setUserName(String userName) { + this.userName = userName; + return this; + } - public Byte getUserAge() { - return userAge; - } + public Byte getUserAge() { + return userAge; + } - public User setUserAge(Byte userAge) { - this.userAge = userAge; - return this; - } + public User setUserAge(Byte userAge) { + this.userAge = userAge; + return this; + } - @Override - public String toString() { - return "User{" + - "userName='" + userName + '\'' + - ", userAge=" + userAge + - '}'; - } - } \ No newline at end of file + @Override + public String toString() { + return "User{" + + "userName='" + userName + '\'' + + ", userAge=" + userAge + + '}'; + } +} \ No newline at end of file diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java index e1f4f54a..392748a8 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java @@ -25,11 +25,11 @@ * RocketMQMessageListener */ @Service -@RocketMQMessageListener(nameServer = "${demo.rocketmq.myNameServer}",topic = "${demo.rocketmq.topic.user}", consumerGroup = "user_consumer") +@RocketMQMessageListener(nameServer = "${demo.rocketmq.myNameServer}", topic = "${demo.rocketmq.topic.user}", consumerGroup = "user_consumer") public class UserConsumer implements RocketMQListener { @Override public void onMessage(User message) { - System.out.printf("######## user_consumer received: %s ; age: %s ; name: %s \n", message,message.getUserAge(),message.getUserName()); + System.out.printf("######## user_consumer received: %s ; age: %s ; name: %s \n", message, message.getUserAge(), message.getUserName()); } } 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 3a07d936..2bec6fd5 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 @@ -74,14 +74,13 @@ public void run(String... args) throws Exception { SendResult sendResult = rocketMQTemplate.syncSend(springTopic, "Hello, World!"); System.out.printf("syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); - SendResult sendResult2 = rocketMQTemplate.syncSend(userTopic, new User().setUserAge((byte) 18).setUserName("平头哥")); + SendResult sendResult2 = rocketMQTemplate.syncSend(userTopic, new User().setUserAge((byte)18).setUserName("Kitty")); System.out.printf("syncSend1 to topic %s sendResult=%s %n", userTopic, sendResult2); SendResult sendResult3 = rocketMQTemplate.syncSend(userTopic, MessageBuilder.withPayload( - new User().setUserAge((byte) 21).setUserName("小火箭")).setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE).build()); + new User().setUserAge((byte)21).setUserName("Lester")).setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE).build()); System.out.printf("syncSend1 to topic %s sendResult=%s %n", userTopic, sendResult3); - // Use the extRocketMQTemplate sendResult = extRocketMQTemplate.syncSend(springTopic, MessageBuilder.withPayload("Hello, World!2222".getBytes()).build()); System.out.printf("extRocketMQTemplate.syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); @@ -110,7 +109,6 @@ public void onException(Throwable var1) { rocketMQTemplate.convertAndSend(msgExtTopic + ":tag1", "I'm from tag1"); System.out.printf("syncSend topic %s tag %s %n", msgExtTopic, "tag1"); - // Send a batch of strings testBatchMessages(); @@ -122,7 +120,7 @@ private void testBatchMessages() { List msgs = new ArrayList(); for (int i = 0; i < 10; i++) { msgs.add(MessageBuilder.withPayload("Hello RocketMQ Batch Msg#" + i). - setHeader(RocketMQHeaders.KEYS, "KEY_" + i).build()); + setHeader(RocketMQHeaders.KEYS, "KEY_" + i).build()); } SendResult sr = rocketMQTemplate.syncSend(springTopic, msgs, 60000); @@ -130,9 +128,8 @@ private void testBatchMessages() { System.out.printf("--- Batch messages send result :" + sr); } - private void testTransaction() throws MessagingException { - String[] tags = new String[]{"TagA", "TagB", "TagC", "TagD", "TagE"}; + String[] tags = new String[] {"TagA", "TagB", "TagC", "TagD", "TagE"}; for (int i = 0; i < 10; i++) { try { @@ -144,7 +141,8 @@ private void testTransaction() throws MessagingException { msg.getPayload(), sendResult.getSendStatus()); Thread.sleep(10); - } catch (Exception e) { + } + catch (Exception e) { e.printStackTrace(); } } @@ -207,7 +205,7 @@ public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { } } - class User{ + class User { private String userName; private Byte userAge; @@ -232,11 +230,10 @@ public User setUserAge(Byte userAge) { @Override public String toString() { return "User{" + - "userName='" + userName + '\'' + - ", userAge=" + userAge + - '}'; + "userName='" + userName + '\'' + + ", userAge=" + userAge + + '}'; } } - } From 4294eb046332f70136412593c1af6e30b49724e5 Mon Sep 17 00:00:00 2001 From: zkzlx Date: Sat, 12 Oct 2019 23:24:00 +0800 Subject: [PATCH 025/105] solve the problems arising from review --- .../springboot/consumer/UserConsumer.java | 1 + .../springboot/{consumer => domain}/User.java | 2 +- .../springboot/ProducerApplication.java | 43 +++------------- .../samples/springboot/domain/User.java | 49 +++++++++++++++++++ .../ExtProducerResetConfiguration.java | 6 +-- .../JacksonFallbackConfiguration.java | 1 + .../ListenerContainerConfiguration.java | 3 +- .../RocketMQAutoConfiguration.java | 3 +- .../spring/core/RocketMQTemplate.java | 36 +++++--------- .../DefaultRocketMQListenerContainer.java | 5 +- .../support/RocketMQMessageConverter.java | 4 +- .../rocketmq/spring/support/RocketMQUtil.java | 24 +++------ 12 files changed, 88 insertions(+), 89 deletions(-) rename rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/{consumer => domain}/User.java (96%) create mode 100644 rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/User.java diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java index 392748a8..b9e36475 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/UserConsumer.java @@ -17,6 +17,7 @@ package org.apache.rocketmq.samples.springboot.consumer; +import org.apache.rocketmq.samples.springboot.domain.User; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQListener; import org.springframework.stereotype.Service; diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/User.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/User.java similarity index 96% rename from rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/User.java rename to rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/User.java index e020fc27..4f2579f6 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/User.java +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/User.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.rocketmq.samples.springboot.consumer; +package org.apache.rocketmq.samples.springboot.domain; public class User { private String userName; 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 2bec6fd5..8abc4ff2 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 @@ -20,6 +20,7 @@ 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.samples.springboot.domain.User; import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; @@ -74,12 +75,12 @@ public void run(String... args) throws Exception { SendResult sendResult = rocketMQTemplate.syncSend(springTopic, "Hello, World!"); System.out.printf("syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); - SendResult sendResult2 = rocketMQTemplate.syncSend(userTopic, new User().setUserAge((byte)18).setUserName("Kitty")); - System.out.printf("syncSend1 to topic %s sendResult=%s %n", userTopic, sendResult2); + sendResult = rocketMQTemplate.syncSend(userTopic, new User().setUserAge((byte)18).setUserName("Kitty")); + System.out.printf("syncSend1 to topic %s sendResult=%s %n", userTopic, sendResult); - SendResult sendResult3 = rocketMQTemplate.syncSend(userTopic, MessageBuilder.withPayload( + sendResult = rocketMQTemplate.syncSend(userTopic, MessageBuilder.withPayload( new User().setUserAge((byte)21).setUserName("Lester")).setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE).build()); - System.out.printf("syncSend1 to topic %s sendResult=%s %n", userTopic, sendResult3); + System.out.printf("syncSend1 to topic %s sendResult=%s %n", userTopic, sendResult); // Use the extRocketMQTemplate sendResult = extRocketMQTemplate.syncSend(springTopic, MessageBuilder.withPayload("Hello, World!2222".getBytes()).build()); @@ -141,8 +142,7 @@ private void testTransaction() throws MessagingException { msg.getPayload(), sendResult.getSendStatus()); Thread.sleep(10); - } - catch (Exception e) { + } catch (Exception e) { e.printStackTrace(); } } @@ -205,35 +205,4 @@ public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { } } - class User { - private String userName; - private Byte userAge; - - public String getUserName() { - return userName; - } - - public User setUserName(String userName) { - this.userName = userName; - return this; - } - - public Byte getUserAge() { - return userAge; - } - - public User setUserAge(Byte userAge) { - this.userAge = userAge; - return this; - } - - @Override - public String toString() { - return "User{" + - "userName='" + userName + '\'' + - ", userAge=" + userAge + - '}'; - } - } - } diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/User.java b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/User.java new file mode 100644 index 00000000..42acc11e --- /dev/null +++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/User.java @@ -0,0 +1,49 @@ +/* + * 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; + +public class User { + private String userName; + private Byte userAge; + + public String getUserName() { + return userName; + } + + public User setUserName(String userName) { + this.userName = userName; + return this; + } + + public Byte getUserAge() { + return userAge; + } + + public User setUserAge(Byte userAge) { + this.userAge = userAge; + return this; + } + + @Override + public String toString() { + return "User{" + + "userName='" + userName + '\'' + + ", userAge=" + userAge + + '}'; + } + } \ No newline at end of file diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index 8bf061b3..0e1e37e6 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -95,8 +95,7 @@ private void registerTemplate(String beanName, Object bean) { mqProducer.setInstanceName(beanName); try { mqProducer.start(); - } - catch (MQClientException e) { + } catch (MQClientException e) { throw new BeanDefinitionValidationException(String.format("Failed to startup MQProducer for RocketMQTemplate {}", beanName), e); } @@ -129,8 +128,7 @@ private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annota producer = new DefaultMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk)), annotation.enableMsgTrace(), customizedTraceTopic); producer.setVipChannelEnabled(false); - } - else { + } else { producer = new DefaultMQProducer(groupName, annotation.enableMsgTrace(), customizedTraceTopic); } diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java index d25ca8d8..b6518c0f 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java @@ -24,6 +24,7 @@ @Configuration @ConditionalOnMissingBean(ObjectMapper.class) +@Deprecated class JacksonFallbackConfiguration { @Bean diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index 82d90d23..9d65d754 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -118,8 +118,7 @@ private void registerContainer(String beanName, Object bean) { if (!container.isRunning()) { try { container.start(); - } - catch (Exception e) { + } catch (Exception e) { log.error("Started container failed. {}", container, e); throw new RuntimeException(e); } diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java index 91b26096..dbe697b7 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java @@ -91,8 +91,7 @@ public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties rocketMQProperties.getProducer().isEnableMsgTrace(), rocketMQProperties.getProducer().getCustomizedTraceTopic()); producer.setVipChannelEnabled(false); - } - else { + } else { producer = new DefaultMQProducer(groupName, rocketMQProperties.getProducer().isEnableMsgTrace(), rocketMQProperties.getProducer().getCustomizedTraceTopic()); } 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 51f442ad..682bbbe5 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 @@ -160,8 +160,7 @@ public SendResult syncSend(String destination, Collection> messages, log.debug("send messages cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } - catch (Exception e) { + } catch (Exception e) { log.error("syncSend with batch failed. destination:{}, messages.size:{} ", destination, messages.size()); throw new MessagingException(e.getMessage(), e); } @@ -193,8 +192,7 @@ public SendResult syncSend(String destination, Message message, long timeout, log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } - catch (Exception e) { + } catch (Exception e) { log.error("syncSend failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -259,8 +257,7 @@ public SendResult syncSendOrderly(String destination, Message message, String log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } - catch (Exception e) { + } catch (Exception e) { log.error("syncSendOrderly failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -314,8 +311,7 @@ public void asyncSend(String destination, Message message, SendCallback sendC rocketMsg.setDelayTimeLevel(delayLevel); } producer.send(rocketMsg, sendCallback, timeout); - } - catch (Exception e) { + } catch (Exception e) { log.info("asyncSend failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -335,8 +331,7 @@ public void asyncSend(String destination, Message message, SendCallback sendC /** *

Send message to broker asynchronously. asynchronous transmission is generally used in response time - * sensitive - * business scenarios.

+ * sensitive business scenarios.

*

* This method returns immediately. On sending completion, sendCallback will be executed. *

@@ -395,8 +390,7 @@ public void asyncSendOrderly(String destination, Message message, String hash try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.send(rocketMsg, messageQueueSelector, hashKey, sendCallback, timeout); - } - catch (Exception e) { + } catch (Exception e) { log.error("asyncSendOrderly failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -458,8 +452,7 @@ public void sendOneWay(String destination, Message message) { try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.sendOneway(rocketMsg); - } - catch (Exception e) { + } catch (Exception e) { log.error("sendOneWay failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -491,8 +484,7 @@ public void sendOneWayOrderly(String destination, Message message, String has try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.sendOneway(rocketMsg, messageQueueSelector, hashKey); - } - catch (Exception e) { + } catch (Exception e) { log.error("sendOneWayOrderly failed. destination:{}, message:{}", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -577,8 +569,7 @@ public TransactionSendResult sendMessageInTransaction(final String txProducerGro TransactionMQProducer txProducer = this.stageMQProducer(txProducerGroup); org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); return txProducer.sendMessageInTransaction(rocketMsg, arg); - } - catch (MQClientException e) { + } catch (MQClientException e) { throw RocketMQUtil.convert(e); } } @@ -586,8 +577,7 @@ public TransactionSendResult sendMessageInTransaction(final String txProducerGro /** * Remove a TransactionMQProducer from cache by manual. *

Note: RocketMQTemplate can release all cached producers when bean destroying, it is not recommended to - * directly - * use this method by user. + * directly use this method by user. * * @param txProducerGroup * @throws MessagingException @@ -626,8 +616,7 @@ public boolean createAndStartTransactionMQProducer(String txProducerGroup, try { txProducer.start(); cache.put(txProducerGroup, txProducer); - } - catch (MQClientException e) { + } catch (MQClientException e) { throw RocketMQUtil.convert(e); } @@ -644,8 +633,7 @@ private TransactionMQProducer createTransactionMQProducer(String name, txProducer = new TransactionMQProducer(name, rpcHook); txProducer.setVipChannelEnabled(false); txProducer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, name)); - } - else { + } else { txProducer = new TransactionMQProducer(name); } txProducer.setTransactionListener(RocketMQUtil.convert(transactionListener)); 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 c38db99b..67d06dc5 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 @@ -88,6 +88,7 @@ public class DefaultRocketMQListenerContainer implements InitializingBean, private String charset = "UTF-8"; + @Deprecated private ObjectMapper objectMapper; private MessageConverter messageConverter; @@ -169,10 +170,12 @@ public void setCharset(String charset) { this.charset = charset; } + @Deprecated public ObjectMapper getObjectMapper() { return objectMapper; } + @Deprecated public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } @@ -389,7 +392,7 @@ private Object doConvertMessage(MessageExt messageExt) { } else { // If msgType not string, use objectMapper change it. try { - return messageConverter.fromMessage(MessageBuilder.withPayload(str).build(),messageType); + return this.getMessageConverter().fromMessage(MessageBuilder.withPayload(str).build(), messageType); } catch (Exception e) { log.info("convert failed. str:{}, msgType:{}", str, messageType); throw new RuntimeException("cannot convert message to " + messageType, e); diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java index f8dbee95..c2ee1daf 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java @@ -64,8 +64,8 @@ public RocketMQMessageConverter() { (MessageConverter)ClassUtils.forName( "com.alibaba.fastjson.support.spring.messaging.MappingFastJsonMessageConverter", ClassUtils.getDefaultClassLoader()).newInstance()); - } - catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { + } catch (ClassNotFoundException | IllegalAccessException | InstantiationException ignored) { + //ignore this exception } } messageConverter = new CompositeMessageConverter(messageConverters); 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 index 720486de..735609be 100644 --- 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 @@ -137,16 +137,13 @@ public static org.apache.rocketmq.common.message.Message convertToRocketMessage( if (payloadObj instanceof String) { payloads = ((String)payloadObj).getBytes(Charset.forName(charset)); - } - else if (payloadObj instanceof byte[]) { + } else if (payloadObj instanceof byte[]) { payloads = (byte[])message.getPayload(); - } - else { + } else { try { String jsonObj = objectMapper.writeValueAsString(payloadObj); payloads = jsonObj.getBytes(Charset.forName(charset)); - } - catch (Exception e) { + } catch (Exception e) { throw new RuntimeException("convert to RocketMQ message failed.", e); } } @@ -181,8 +178,7 @@ private static Message getAndWrapMessage(String destination, MessageHeaders head int flag = 0; try { flag = Integer.parseInt(flagObj.toString()); - } - catch (NumberFormatException e) { + } catch (NumberFormatException e) { // Ignore it if (log.isInfoEnabled()) { log.info("flag must be integer, flagObj:{}", flagObj); @@ -215,11 +211,9 @@ public static org.apache.rocketmq.common.message.Message convertToRocketMessage( } if (payloadObj instanceof String) { payloads = ((String)payloadObj).getBytes(Charset.forName(charset)); - } - else if (payloadObj instanceof byte[]) { + } else if (payloadObj instanceof byte[]) { payloads = (byte[])message.getPayload(); - } - else { + } else { String jsonObj = (String)messageConverter.fromMessage(message, payloadObj.getClass()); if (null == jsonObj) { throw new RuntimeException(String.format( @@ -228,8 +222,7 @@ else if (payloadObj instanceof byte[]) { } payloads = jsonObj.getBytes(Charset.forName(charset)); } - } - catch (Exception e) { + } catch (Exception e) { throw new RuntimeException("convert to RocketMQ message failed.", e); } return getAndWrapMessage(destination, message.getHeaders(), payloads); @@ -240,8 +233,7 @@ public static RPCHook getRPCHookByAkSk(Environment env, String accessKeyOrExpr, try { ak = env.resolveRequiredPlaceholders(accessKeyOrExpr); sk = env.resolveRequiredPlaceholders(secretKeyOrExpr); - } - catch (Exception e) { + } catch (Exception e) { // Ignore it ak = null; sk = null; From be8b8a4b18154225a58bb6393898a58b7401bd9b Mon Sep 17 00:00:00 2001 From: 16534 <16534@DESKTOP-136P21N> Date: Mon, 28 Oct 2019 16:39:45 +0800 Subject: [PATCH 026/105] fix:#103 support resolvePlaceholders for selectorExpression codestyle and update test class with actual meaning. --- .../RocketMQAutoConfigurationTest.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index 4457b95f..a865e3d4 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -130,7 +130,7 @@ public void testRocketMQListenerWithSeveralObjectMappers() { @Test public void testExtRocketMQTemplate() { runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). - withUserConfiguration(ExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). + withUserConfiguration(TestExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). run(new ContextConsumer() { @Override public void accept(AssertableApplicationContext context) throws Throwable { @@ -141,7 +141,7 @@ public void accept(AssertableApplicationContext context) throws Throwable { }); runner.withPropertyValues("rocketmq.name-server=127.0.1.1:9876"). - withUserConfiguration(ExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). + withUserConfiguration(TestExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). run((context) -> { // No producer on consume side assertThat(context).getBean("extRocketMQTemplate").hasFieldOrProperty("producer"); @@ -202,12 +202,12 @@ static class TestConfig { @Bean public Object consumeListener() { - return new MyMessageListener(); + return new TestDefaultNameServerListener(); } @Bean public Object consumeListener1() { - return new MyMessageListener1(); + return new TestCustomNameServerListener(); } } @@ -238,7 +238,7 @@ public ObjectMapper rocketMQMessageObjectMapper() { } @RocketMQMessageListener(consumerGroup = "abc", topic = "test") - static class MyMessageListener implements RocketMQListener { + static class TestDefaultNameServerListener implements RocketMQListener { @Override public void onMessage(Object message) { @@ -247,7 +247,7 @@ public void onMessage(Object message) { } @RocketMQMessageListener(nameServer = "127.0.1.1:9876", consumerGroup = "abc1", topic = "test") - static class MyMessageListener1 implements RocketMQListener { + static class TestCustomNameServerListener implements RocketMQListener { @Override public void onMessage(Object message) { @@ -280,17 +280,17 @@ public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { } @Configuration - static class ExtRocketMQTemplateConfig { + static class TestExtRocketMQTemplateConfig { @Bean public RocketMQTemplate extRocketMQTemplate() { - return new MyExtRocketMQTemplate(); + return new TestExtRocketMQTemplate(); } } @ExtRocketMQTemplateConfiguration(group = "test", nameServer = "127.0.0.1:9876") - static class MyExtRocketMQTemplate extends RocketMQTemplate { + static class TestExtRocketMQTemplate extends RocketMQTemplate { } From 24ac48d5994a6f2bed9d97ecff4f534a059416ca Mon Sep 17 00:00:00 2001 From: 16534 <16534@DESKTOP-136P21N> Date: Mon, 28 Oct 2019 16:42:39 +0800 Subject: [PATCH 027/105] fix:#103 support resolvePlaceholders for selectorExpression codestyle and update test class with actual meaning. --- .../spring/autoconfigure/RocketMQAutoConfigurationTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index a865e3d4..9fa0fa41 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -170,7 +170,7 @@ public void testRocketMQTransactionListener() { "demo.rocketmq.transaction.producer.group=transaction-group1"). withUserConfiguration(TestTransactionListenerConfig.class). run((context) -> { - assertThat(context).hasSingleBean(MyRocketMQLocalTransactionListener.class); + assertThat(context).hasSingleBean(TestRocketMQLocalTransactionListener.class); }); @@ -259,13 +259,13 @@ public void onMessage(Object message) { static class TestTransactionListenerConfig { @Bean public Object rocketMQLocalTransactionListener() { - return new MyRocketMQLocalTransactionListener(); + return new TestRocketMQLocalTransactionListener(); } } @RocketMQTransactionListener(txProducerGroup = "${demo.rocketmq.transaction.producer.group}") - static class MyRocketMQLocalTransactionListener implements RocketMQLocalTransactionListener { + static class TestRocketMQLocalTransactionListener implements RocketMQLocalTransactionListener { @Override From 23690b8c45980542ec2c6bc11e1158b22b2c3652 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Thu, 31 Oct 2019 15:19:19 +0800 Subject: [PATCH 028/105] fix(transaction):fix transactionProducer has incorrect namespace --- .../java/org/apache/rocketmq/spring/core/RocketMQTemplate.java | 1 + 1 file changed, 1 insertion(+) 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 be4d1949..e70d3046 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 @@ -660,6 +660,7 @@ private TransactionMQProducer createTransactionMQProducer(String name, } txProducer.setTransactionListener(RocketMQUtil.convert(transactionListener)); + txProducer.setNamespace(producer.getNamespace()); txProducer.setNamesrvAddr(producer.getNamesrvAddr()); if (executorService != null) { txProducer.setExecutorService(executorService); From e10cc5e68ff42cb5693655186734677d8df0d7cd Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 31 Oct 2019 16:45:41 +0800 Subject: [PATCH 029/105] [ISSUE #81]Fix RocketMQTemplate.syncSend collection type method signature (#150) * fix RocketMQTemplate.syncSend collection type method signature * add a custom batch message send test code; * change batch message send unit test code --- .../spring/core/RocketMQTemplate.java | 4 +-- .../rocketmq/spring/support/RocketMQUtil.java | 2 +- .../RocketMQAutoConfigurationTest.java | 29 ++++++++++++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) 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 e70d3046..528615db 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 @@ -134,7 +134,7 @@ public SendResult syncSend(String destination, Message message, long timeout) * @param timeout send timeout with millis * @return {@link SendResult} */ - public SendResult syncSend(String destination, Collection> messages, long timeout) { + public SendResult syncSend(String destination, Collection messages, long timeout) { if (Objects.isNull(messages) || messages.size() == 0) { log.error("syncSend with batch failed. destination:{}, messages is empty ", destination); throw new IllegalArgumentException("`messages` can not be empty"); @@ -144,7 +144,7 @@ public SendResult syncSend(String destination, Collection> messages, long now = System.currentTimeMillis(); Collection rmqMsgs = new ArrayList<>(); org.apache.rocketmq.common.message.Message rocketMsg; - for (Message msg:messages) { + for (Message msg:messages) { if (Objects.isNull(msg) || Objects.isNull(msg.getPayload())) { log.warn("Found a message empty in the batch, skip it"); continue; 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 index d10cb1b6..f4deb458 100644 --- 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 @@ -129,7 +129,7 @@ public static org.springframework.messaging.Message convertToSpringMessage( public static org.apache.rocketmq.common.message.Message convertToRocketMessage( ObjectMapper objectMapper, String charset, - String destination, org.springframework.messaging.Message message) { + String destination, org.springframework.messaging.Message message) { Object payloadObj = message.getPayload(); byte[] payloads; diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index 9fa0fa41..8f2a5abf 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -19,6 +19,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.client.producer.SendStatus; import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; @@ -38,6 +40,11 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.Message; +import org.springframework.messaging.MessagingException; +import org.springframework.messaging.support.GenericMessage; + +import java.util.ArrayList; +import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @@ -177,6 +184,27 @@ public void testRocketMQTransactionListener() { } @Test + public void testBatchSendMessage() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", + "rocketmq.producer.group=spring_rocketmq"). + run((context) -> { + RocketMQTemplate rocketMQTemplate = context.getBean(RocketMQTemplate.class); + List> batchMessages = new ArrayList>(); + + String errorMsg = null; + try { + SendResult customSendResult = rocketMQTemplate.syncSend("test", batchMessages, 60000); + } catch (IllegalArgumentException e) { + // it will be throw IllegalArgumentException: `messages` can not be empty + errorMsg = e.getMessage(); + } + + // that means the rocketMQTemplate.syncSend is chosen the correct type method + Assert.assertEquals("`messages` can not be empty", errorMsg); + }); + + } + public void testPlaceholdersListenerContainer() { runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", "demo.placeholders.consumer.group = abc3", @@ -196,7 +224,6 @@ public void testPlaceholdersListenerContainer() { }); } - @Configuration static class TestConfig { From ee4b5a71d8a13261e510cc54f4d4f61babd46a2f Mon Sep 17 00:00:00 2001 From: ShannonDing Date: Tue, 12 Nov 2019 10:09:05 +0800 Subject: [PATCH 030/105] [maven-release-plugin] prepare release rocketmq-spring-all-2.0.4 --- pom.xml | 4 ++-- rocketmq-spring-boot-parent/pom.xml | 4 ++-- rocketmq-spring-boot-starter/pom.xml | 2 +- rocketmq-spring-boot/pom.xml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 921d16ea..d1df409f 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.0.4-SNAPSHOT + 2.0.4 pom Apache RocketMQ Spring Boot ${project.version} @@ -39,7 +39,7 @@ git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git - HEAD + rocketmq-spring-all-2.0.4 diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index 21cf25be..f891a9aa 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.0.4-SNAPSHOT + 2.0.4 ../pom.xml @@ -38,7 +38,7 @@ 2.0.5.RELEASE 5.1.0.RELEASE - 2.0.4-SNAPSHOT + 2.0.4 4.5.2 1.7.25 diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml index 5392ec82..894162e5 100644 --- a/rocketmq-spring-boot-starter/pom.xml +++ b/rocketmq-spring-boot-starter/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.0.4-SNAPSHOT + 2.0.4 ../rocketmq-spring-boot-parent/pom.xml diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml index 289a53ff..b00ee456 100644 --- a/rocketmq-spring-boot/pom.xml +++ b/rocketmq-spring-boot/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.0.4-SNAPSHOT + 2.0.4 ../rocketmq-spring-boot-parent/pom.xml From 96289becbcd377638ae18397966521757f24b319 Mon Sep 17 00:00:00 2001 From: ShannonDing Date: Tue, 12 Nov 2019 10:09:27 +0800 Subject: [PATCH 031/105] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- rocketmq-spring-boot-parent/pom.xml | 4 ++-- rocketmq-spring-boot-starter/pom.xml | 2 +- rocketmq-spring-boot/pom.xml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index d1df409f..f8acf1d0 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.0.4 + 2.0.5-SNAPSHOT pom Apache RocketMQ Spring Boot ${project.version} @@ -39,7 +39,7 @@ git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git - rocketmq-spring-all-2.0.4 + HEAD diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index f891a9aa..8352241a 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.0.4 + 2.0.5-SNAPSHOT ../pom.xml @@ -38,7 +38,7 @@ 2.0.5.RELEASE 5.1.0.RELEASE - 2.0.4 + 2.0.5-SNAPSHOT 4.5.2 1.7.25 diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml index 894162e5..697ab169 100644 --- a/rocketmq-spring-boot-starter/pom.xml +++ b/rocketmq-spring-boot-starter/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.0.4 + 2.0.5-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml index b00ee456..d5d5505f 100644 --- a/rocketmq-spring-boot/pom.xml +++ b/rocketmq-spring-boot/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.0.4 + 2.0.5-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml From e1c8019fd5b48a9a0fc3827728156aef9b81fc1e Mon Sep 17 00:00:00 2001 From: ShannonDing Date: Fri, 15 Nov 2019 14:16:16 +0800 Subject: [PATCH 032/105] fix(doc):update the year in NOTICE and upgrade the spring version to 2.0.4 in README --- NOTICE | 2 +- README.md | 2 +- README_zh_CN.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NOTICE b/NOTICE index f07078d7..85e2dc3f 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache RocketMQ -Copyright 2016-2018 The Apache Software Foundation +Copyright 2016-2019 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 c7504b8a..04a9334e 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,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.3 +Note: Current RELEASE.VERSION=2.0.4 ```xml diff --git a/README_zh_CN.md b/README_zh_CN.md index fe26aa8b..3e263074 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -35,7 +35,7 @@ 下面列出来了一些关键点,完整的示例请参考: [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples) -注意:当前的RELEASE.VERSION=2.0.3 +注意:当前的RELEASE.VERSION=2.0.4 ```xml From 95d247c5a2f9f67ea900b183017388a2cb1be095 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Tue, 26 Nov 2019 22:06:05 +0800 Subject: [PATCH 033/105] refactor(transaction):refactor transaction message implementation --- rocketmq-spring-boot-parent/pom.xml | 2 +- rocketmq-spring-boot-samples/pom.xml | 2 +- .../springboot/ProducerACLApplication.java | 9 +- .../springboot/ProducerApplication.java | 5 +- .../RocketMQTransactionListener.java | 21 +-- .../RocketMQAutoConfiguration.java | 46 ++++--- ...ocketMQTransactionAnnotationProcessor.java | 45 +++---- .../spring/config/TransactionHandler.java | 85 ------------- .../config/TransactionHandlerRegistry.java | 52 -------- .../spring/core/RocketMQTemplate.java | 120 +----------------- .../RocketMQAutoConfigurationTest.java | 43 +------ 11 files changed, 54 insertions(+), 376 deletions(-) delete mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandler.java delete mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index 8352241a..ca490b01 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -40,7 +40,7 @@ 2.0.5-SNAPSHOT - 4.5.2 + 4.6.0 1.7.25 2.9.7 diff --git a/rocketmq-spring-boot-samples/pom.xml b/rocketmq-spring-boot-samples/pom.xml index c513a5d1..983a2d49 100644 --- a/rocketmq-spring-boot-samples/pom.xml +++ b/rocketmq-spring-boot-samples/pom.xml @@ -38,7 +38,7 @@ - 2.0.4-SNAPSHOT + 2.0.5-SNAPSHOT diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerACLApplication.java b/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerACLApplication.java index 498c2e12..486a4138 100644 --- a/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerACLApplication.java +++ b/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerACLApplication.java @@ -41,7 +41,6 @@ */ @SpringBootApplication public class ProducerACLApplication implements CommandLineRunner { - private static final String TX_PGROUP_NAME = "myTxProducerGroup"; @Resource private RocketMQTemplate rocketMQTemplate; @Value("${demo.rocketmq.transTopic}") @@ -75,7 +74,7 @@ private void testTransaction() throws MessagingException { Message msg = MessageBuilder.withPayload("Hello RocketMQ " + i). setHeader(RocketMQHeaders.TRANSACTION_ID, "KEY_" + i).build(); - SendResult sendResult = rocketMQTemplate.sendMessageInTransaction(TX_PGROUP_NAME, + SendResult sendResult = rocketMQTemplate.sendMessageInTransaction( springTransTopic + ":" + tags[i % tags.length], msg, null); System.out.printf("------ send Transactional msg body = %s , sendResult=%s %n", msg.getPayload(), sendResult.getSendStatus()); @@ -87,11 +86,7 @@ private void testTransaction() throws MessagingException { } } - @RocketMQTransactionListener( - txProducerGroup = TX_PGROUP_NAME, - accessKey = "AK", // if not setting, it will read by `rocketmq.producer.access-key` key - secretKey = "SK" // if not setting, it will read by `rocketmq.producer.secret-key` key - ) + @RocketMQTransactionListener class TransactionListenerImpl implements RocketMQLocalTransactionListener { private AtomicInteger transactionIndex = new AtomicInteger(0); 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 8abc4ff2..4771bea3 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 @@ -48,7 +48,6 @@ */ @SpringBootApplication public class ProducerApplication implements CommandLineRunner { - private static final String TX_PGROUP_NAME = "myTxProducerGroup"; @Resource private RocketMQTemplate rocketMQTemplate; @Value("${demo.rocketmq.transTopic}") @@ -136,7 +135,7 @@ private void testTransaction() throws MessagingException { Message msg = MessageBuilder.withPayload("Hello RocketMQ " + i). setHeader(RocketMQHeaders.TRANSACTION_ID, "KEY_" + i).build(); - SendResult sendResult = rocketMQTemplate.sendMessageInTransaction(TX_PGROUP_NAME, + SendResult sendResult = rocketMQTemplate.sendMessageInTransaction( springTransTopic + ":" + tags[i % tags.length], msg, null); System.out.printf("------ send Transactional msg body = %s , sendResult=%s %n", msg.getPayload(), sendResult.getSendStatus()); @@ -148,7 +147,7 @@ private void testTransaction() throws MessagingException { } } - @RocketMQTransactionListener(txProducerGroup = TX_PGROUP_NAME) + @RocketMQTransactionListener class TransactionListenerImpl implements RocketMQLocalTransactionListener { private AtomicInteger transactionIndex = new AtomicInteger(0); 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 index f3f874cf..c65ffc69 100644 --- 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 @@ -17,14 +17,12 @@ 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; +import org.springframework.stereotype.Component; /** * This annotation is used over a class which implements interface @@ -39,14 +37,6 @@ @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. - *

- *

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 */ @@ -67,13 +57,4 @@ */ int blockingQueueSize() default 2000; - /** - * The property of "access-key" - */ - String accessKey() default "${rocketmq.producer.access-key}"; - - /** - * The property of "secret-key" - */ - String secretKey() default "${rocketmq.producer.secret-key}"; } diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java index dbe697b7..f4abf723 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java @@ -17,16 +17,19 @@ package org.apache.rocketmq.spring.autoconfigure; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.lang.reflect.Field; import javax.annotation.PostConstruct; - import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.client.MQAdmin; import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.client.trace.AsyncTraceDispatcher; +import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl; 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.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.slf4j.Logger; @@ -48,8 +51,6 @@ import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import com.fasterxml.jackson.databind.ObjectMapper; - @Configuration @EnableConfigurationProperties(RocketMQProperties.class) @ConditionalOnClass({MQAdmin.class, ObjectMapper.class}) @@ -86,14 +87,26 @@ public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties DefaultMQProducer producer; String ak = rocketMQProperties.getProducer().getAccessKey(); String sk = rocketMQProperties.getProducer().getSecretKey(); - if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { - producer = new DefaultMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk)), - rocketMQProperties.getProducer().isEnableMsgTrace(), - rocketMQProperties.getProducer().getCustomizedTraceTopic()); + boolean isEnableAcl = !StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk); + if (isEnableAcl) { + producer = new TransactionMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk))); producer.setVipChannelEnabled(false); } else { - producer = new DefaultMQProducer(groupName, rocketMQProperties.getProducer().isEnableMsgTrace(), - rocketMQProperties.getProducer().getCustomizedTraceTopic()); + producer = new TransactionMQProducer(groupName); + } + + if (rocketMQProperties.getProducer().isEnableMsgTrace()) { + try { + AsyncTraceDispatcher dispatcher = new AsyncTraceDispatcher(rocketMQProperties.getProducer().getCustomizedTraceTopic(), isEnableAcl ? new AclClientRPCHook(new SessionCredentials(ak, sk)) : null); + dispatcher.setHostProducer(producer.getDefaultMQProducerImpl()); + Field field = DefaultMQProducer.class.getDeclaredField("traceDispatcher"); + field.setAccessible(true); + field.set(producer, dispatcher); + producer.getDefaultMQProducerImpl().registerSendMessageHook( + new SendMessageTraceHookImpl(dispatcher)); + } catch (Throwable e) { + log.error("system mqtrace hook init failed ,maybe can't send msg trace data"); + } } producer.setNamesrvAddr(nameServer); @@ -123,20 +136,13 @@ public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, return rocketMQTemplate; } - @Bean - @ConditionalOnBean(name = RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) - @ConditionalOnMissingBean(TransactionHandlerRegistry.class) - public TransactionHandlerRegistry transactionHandlerRegistry( - @Qualifier(RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) RocketMQTemplate template) { - return new TransactionHandlerRegistry(template); - } @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME) - @ConditionalOnBean(TransactionHandlerRegistry.class) + @ConditionalOnBean(name = RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor( - TransactionHandlerRegistry transactionHandlerRegistry) { - return new RocketMQTransactionAnnotationProcessor(transactionHandlerRegistry); + @Qualifier(RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) RocketMQTemplate template) { + return new RocketMQTransactionAnnotationProcessor(template); } } 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 index 2713bad5..9008d2d2 100644 --- 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 @@ -17,11 +17,20 @@ package org.apache.rocketmq.spring.config; +import java.util.Collections; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.remoting.RPCHook; +import org.apache.rocketmq.client.producer.TransactionMQProducer; import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanCreationException; @@ -31,13 +40,6 @@ import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationUtils; -import java.util.Collections; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class RocketMQTransactionAnnotationProcessor implements BeanPostProcessor, Ordered, ApplicationContextAware { private final static Logger log = LoggerFactory.getLogger(RocketMQTransactionAnnotationProcessor.class); @@ -46,10 +48,10 @@ public class RocketMQTransactionAnnotationProcessor private final Set> nonProcessedClasses = Collections.newSetFromMap(new ConcurrentHashMap, Boolean>(64)); - private TransactionHandlerRegistry transactionHandlerRegistry; + private RocketMQTemplate rocketMQTemplate; - public RocketMQTransactionAnnotationProcessor(TransactionHandlerRegistry transactionHandlerRegistry) { - this.transactionHandlerRegistry = transactionHandlerRegistry; + public RocketMQTransactionAnnotationProcessor(RocketMQTemplate rocketMQTemplate) { + this.rocketMQTemplate = rocketMQTemplate; } @Override @@ -85,7 +87,7 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw private void processTransactionListenerAnnotation(RocketMQTransactionListener listener, Object bean) throws MQClientException { - if (transactionHandlerRegistry == null) { + if (rocketMQTemplate == null) { throw new MQClientException("Bad usage of @RocketMQTransactionListener, " + "the class must work with RocketMQTemplate", null); } @@ -94,24 +96,11 @@ private void processTransactionListenerAnnotation(RocketMQTransactionListener li "the class must implement interface RocketMQLocalTransactionListener", null); } - TransactionHandler transactionHandler = new TransactionHandler(); - transactionHandler.setBeanFactory(this.applicationContext.getAutowireCapableBeanFactory()); - transactionHandler.setName(applicationContext.getEnvironment().resolvePlaceholders(listener.txProducerGroup())); - transactionHandler.setBeanName(bean.getClass().getName()); - transactionHandler.setListener((RocketMQLocalTransactionListener) bean); - transactionHandler.setCheckExecutor(listener.corePoolSize(), listener.maximumPoolSize(), - listener.keepAliveTime(), listener.blockingQueueSize()); - - RPCHook rpcHook = RocketMQUtil.getRPCHookByAkSk(applicationContext.getEnvironment(), - listener.accessKey(), listener.secretKey()); - if (Objects.nonNull(rpcHook)) { - transactionHandler.setRpcHook(rpcHook); - } else { - log.debug("Access-key or secret-key not configure in " + listener + "."); - } + ((TransactionMQProducer) rocketMQTemplate.getProducer()).setExecutorService(new ThreadPoolExecutor(listener.corePoolSize(), listener.maximumPoolSize(), + listener.keepAliveTime(), TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(listener.blockingQueueSize()))); + ((TransactionMQProducer) rocketMQTemplate.getProducer()).setTransactionListener(RocketMQUtil.convert((RocketMQLocalTransactionListener) bean)); - transactionHandlerRegistry.registerTransactionHandler(transactionHandler); } @Override 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 deleted file mode 100644 index f6ce61c3..00000000 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandler.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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.remoting.RPCHook; -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; - private RPCHook rpcHook; - - 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 RPCHook getRpcHook() { - return rpcHook; - } - - public void setRpcHook(RPCHook rpcHook) { - this.rpcHook = rpcHook; - } - - 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 deleted file mode 100644 index 0ec01615..00000000 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 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(), handler.getRpcHook()); - } -} 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 a2431cf3..dd341558 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 @@ -17,23 +17,18 @@ package org.apache.rocketmq.spring.core; +import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.Collection; import java.util.Map; import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutorService; - 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.remoting.RPCHook; -import org.apache.rocketmq.spring.config.RocketMQConfigUtils; import org.apache.rocketmq.spring.support.RocketMQUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,11 +40,8 @@ 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 com.fasterxml.jackson.databind.ObjectMapper; - @SuppressWarnings({"WeakerAccess", "unused"}) public class RocketMQTemplate extends AbstractMessageSendingTemplate implements InitializingBean, DisposableBean { private static final Logger log = LoggerFactory.getLogger(RocketMQTemplate.class); @@ -63,8 +55,6 @@ public class RocketMQTemplate extends AbstractMessageSendingTemplate imp private MessageQueueSelector messageQueueSelector = new SelectMessageQueueByHash(); - private final Map cache = new ConcurrentHashMap<>(); //only put TransactionMQProducer by now!!! - public DefaultMQProducer getProducer() { return producer; } @@ -529,131 +519,27 @@ public void destroy() { if (Objects.nonNull(producer)) { producer.shutdown(); } - for (Map.Entry 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, + public TransactionSendResult sendMessageInTransaction(final String destination, final Message message, final Object arg) throws MessagingException { try { - TransactionMQProducer txProducer = this.stageMQProducer(txProducerGroup); org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); - return txProducer.sendMessageInTransaction(rocketMsg, arg); + return producer.sendMessageInTransaction(rocketMsg, arg); } catch (MQClientException e) { throw RocketMQUtil.convert(e); } } - /** - * Remove a TransactionMQProducer from cache by manual. - *

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. - *

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. - * @param rpcHook 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, RPCHook rpcHook) 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, rpcHook); - 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, RPCHook rpcHook) { - Assert.notNull(producer, "Property 'producer' is required"); - Assert.notNull(transactionListener, "Parameter 'transactionListener' is required"); - TransactionMQProducer txProducer; - if (Objects.nonNull(rpcHook)) { - txProducer = new TransactionMQProducer(name, rpcHook); - txProducer.setVipChannelEnabled(false); - txProducer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, name)); - } else { - txProducer = new TransactionMQProducer(name); - } - txProducer.setTransactionListener(RocketMQUtil.convert(transactionListener)); - - txProducer.setNamespace(producer.getNamespace()); - 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; - } - private org.apache.rocketmq.common.message.Message createRocketMqMessage( String destination, Message message) { Message msg = this.doConvert(message.getPayload(), message.getHeaders(), null); diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index b4c7437c..c2e9ad9c 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -94,47 +94,6 @@ public void testDefaultMQProducer() { } - @Test - public void testRocketMQListenerContainer() { - runner.withPropertyValues("rocketmq.name-server=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).hasBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1"); - assertThat(context).hasBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_2"); - assertThat(context).getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1"). - hasFieldOrPropertyWithValue("nameServer", "127.0.0.1:9876"); - assertThat(context).getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_2"). - hasFieldOrPropertyWithValue("nameServer", "127.0.1.1:9876"); - }); - - } - - @Test - public void testRocketMQListenerWithCustomObjectMapper() { - runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). - withUserConfiguration(TestConfig.class, CustomObjectMapperConfig.class). - run((context) -> { - assertThat(context.getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1", - DefaultRocketMQListenerContainer.class).getMessageConverter()) - .isSameAs(context.getBean(CustomObjectMapperConfig.class).rocketMQMessageConverter().getMessageConverter()); - }); - } - - @Test - public void testRocketMQListenerWithSeveralObjectMappers() { - runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). - withUserConfiguration(TestConfig.class, CustomObjectMappersConfig.class). - run((context) -> { - assertThat(context.getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1", - DefaultRocketMQListenerContainer.class).getMessageConverter()) - .isSameAs(context.getBean(CustomObjectMappersConfig.class).rocketMQMessageConverter().getMessageConverter()); - }); - } - - @Test public void testExtRocketMQTemplate() { runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). @@ -301,7 +260,7 @@ public Object rocketMQLocalTransactionListener() { } - @RocketMQTransactionListener(txProducerGroup = "${demo.rocketmq.transaction.producer.group}") + @RocketMQTransactionListener static class TestRocketMQLocalTransactionListener implements RocketMQLocalTransactionListener { From 5b855a293e6b81a4946dbad0e824c6c852cff0e4 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Wed, 27 Nov 2019 10:04:08 +0800 Subject: [PATCH 034/105] chore(version):change back to 4.5.2 to make CI pass --- 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 ca490b01..8352241a 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -40,7 +40,7 @@ 2.0.5-SNAPSHOT - 4.6.0 + 4.5.2 1.7.25 2.9.7 From 90d3e1a583a01532c57e376da3e6474c24aaea5e Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Mon, 2 Dec 2019 10:21:32 +0800 Subject: [PATCH 035/105] fix(autoconfig):fix selectorExpression cannot autoconfigure from configure file --- rocketmq-spring-boot-samples/pom.xml | 2 +- .../rocketmq/samples/springboot/consumer/StringConsumer.java | 2 +- .../src/main/resources/application.properties | 1 + .../spring/support/DefaultRocketMQListenerContainer.java | 1 - 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rocketmq-spring-boot-samples/pom.xml b/rocketmq-spring-boot-samples/pom.xml index c513a5d1..983a2d49 100644 --- a/rocketmq-spring-boot-samples/pom.xml +++ b/rocketmq-spring-boot-samples/pom.xml @@ -38,7 +38,7 @@ - 2.0.4-SNAPSHOT + 2.0.5-SNAPSHOT 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 2b90c69d..3801d484 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 @@ * RocketMQMessageListener */ @Service -@RocketMQMessageListener(topic = "${demo.rocketmq.topic}", consumerGroup = "string_consumer") +@RocketMQMessageListener(topic = "${demo.rocketmq.topic}", consumerGroup = "string_consumer", selectorExpression = "${demo.rocketmq.tag}") public class StringConsumer implements RocketMQListener { @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 583cde42..b2b2690b 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 @@ -8,6 +8,7 @@ demo.rocketmq.orderTopic=order-paid-topic demo.rocketmq.msgExtTopic=message-ext-topic demo.rocketmq.transTopic=spring-transaction-topic demo.rocketmq.topic.user=user-topic +demo.rocketmq.tag=tagA # another nameserver different global demo.rocketmq.myNameServer=127.0.0.1:9876 \ No newline at end of file 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 603ce664..e59bf4c6 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 @@ -207,7 +207,6 @@ public void setRocketMQMessageListener(RocketMQMessageListener anno) { this.consumeMode = anno.consumeMode(); this.consumeThreadMax = anno.consumeThreadMax(); this.messageModel = anno.messageModel(); - this.selectorExpression = anno.selectorExpression(); this.selectorType = anno.selectorType(); this.consumeTimeout = anno.consumeTimeout(); } From 77922afc2ba627088320fbd2e04791352607a5e8 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Mon, 2 Dec 2019 10:57:20 +0800 Subject: [PATCH 036/105] fix(autoconfig):more elegant optimization --- .../spring/autoconfigure/ListenerContainerConfiguration.java | 5 +---- .../spring/support/DefaultRocketMQListenerContainer.java | 5 ++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index 64626047..27f82647 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -17,11 +17,11 @@ package org.apache.rocketmq.spring.autoconfigure; +import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Collections; import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; - import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.spring.annotation.ConsumeMode; import org.apache.rocketmq.spring.annotation.MessageModel; @@ -43,8 +43,6 @@ import org.springframework.core.env.StandardEnvironment; import org.springframework.util.StringUtils; -import com.fasterxml.jackson.databind.ObjectMapper; - @Configuration public class ListenerContainerConfiguration implements ApplicationContextAware, SmartInitializingSingleton { private final static Logger log = LoggerFactory.getLogger(ListenerContainerConfiguration.class); @@ -146,7 +144,6 @@ private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String container.setSelectorExpression(tags); } container.setConsumerGroup(environment.resolvePlaceholders(annotation.consumerGroup())); - container.setRocketMQMessageListener(annotation); container.setRocketMQListener((RocketMQListener)bean); container.setObjectMapper(objectMapper); container.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); 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 e59bf4c6..c9248641 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 @@ -17,12 +17,12 @@ package org.apache.rocketmq.spring.support; +import com.fasterxml.jackson.databind.ObjectMapper; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.nio.charset.Charset; import java.util.List; import java.util.Objects; - import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.MessageSelector; @@ -54,8 +54,6 @@ import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.Assert; -import com.fasterxml.jackson.databind.ObjectMapper; - @SuppressWarnings("WeakerAccess") public class DefaultRocketMQListenerContainer implements InitializingBean, RocketMQListenerContainer, SmartLifecycle, ApplicationContextAware { @@ -208,6 +206,7 @@ public void setRocketMQMessageListener(RocketMQMessageListener anno) { this.consumeThreadMax = anno.consumeThreadMax(); this.messageModel = anno.messageModel(); this.selectorType = anno.selectorType(); + this.selectorExpression = anno.selectorExpression(); this.consumeTimeout = anno.consumeTimeout(); } From bac2c6904db403ba325cac7357946294916795e0 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 6 Dec 2019 14:23:13 +0800 Subject: [PATCH 037/105] enhancement(autoconfig):delete useless code and ambiguous deprecated annotation about JacksonFallbackConfiguration --- .../ExtProducerResetConfiguration.java | 9 +---- .../JacksonFallbackConfiguration.java | 35 ------------------- .../ListenerContainerConfiguration.java | 7 +--- .../RocketMQAutoConfiguration.java | 9 ++--- .../spring/core/RocketMQTemplate.java | 14 -------- .../DefaultRocketMQListenerContainer.java | 14 -------- .../RocketMQAutoConfigurationTest.java | 2 -- 7 files changed, 5 insertions(+), 85 deletions(-) delete mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index 0e1e37e6..dcb76e9a 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -19,7 +19,6 @@ import java.util.Map; import java.util.Objects; - import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.client.exception.MQClientException; @@ -41,8 +40,6 @@ import org.springframework.core.env.StandardEnvironment; import org.springframework.util.StringUtils; -import com.fasterxml.jackson.databind.ObjectMapper; - @Configuration public class ExtProducerResetConfiguration implements ApplicationContextAware, SmartInitializingSingleton { private final static Logger log = LoggerFactory.getLogger(ExtProducerResetConfiguration.class); @@ -53,14 +50,11 @@ public class ExtProducerResetConfiguration implements ApplicationContextAware, S private RocketMQProperties rocketMQProperties; - private ObjectMapper objectMapper; private RocketMQMessageConverter rocketMQMessageConverter; - public ExtProducerResetConfiguration(ObjectMapper rocketMQMessageObjectMapper, - RocketMQMessageConverter rocketMQMessageConverter, + public ExtProducerResetConfiguration(RocketMQMessageConverter rocketMQMessageConverter, StandardEnvironment environment, RocketMQProperties rocketMQProperties) { this.rocketMQMessageConverter = rocketMQMessageConverter; - this.objectMapper = rocketMQMessageObjectMapper; this.environment = environment; this.rocketMQProperties = rocketMQProperties; } @@ -102,7 +96,6 @@ private void registerTemplate(String beanName, Object bean) { RocketMQTemplate rocketMQTemplate = (RocketMQTemplate)bean; rocketMQTemplate.setProducer(mqProducer); rocketMQTemplate.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); - rocketMQTemplate.setObjectMapper(objectMapper); log.info("Set real producer to :{} {}", beanName, annotation.value()); } diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java deleted file mode 100644 index b6518c0f..00000000 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.autoconfigure; - -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) -@Deprecated -class JacksonFallbackConfiguration { - - @Bean - public ObjectMapper rocketMQMessageObjectMapper() { - return new ObjectMapper(); - } - -} diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index 27f82647..7bda36cb 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -17,7 +17,6 @@ package org.apache.rocketmq.spring.autoconfigure; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Collections; import java.util.Map; import java.util.Objects; @@ -55,13 +54,10 @@ public class ListenerContainerConfiguration implements ApplicationContextAware, private RocketMQProperties rocketMQProperties; - private ObjectMapper objectMapper; private RocketMQMessageConverter rocketMQMessageConverter; - public ListenerContainerConfiguration(ObjectMapper rocketMQMessageObjectMapper, - RocketMQMessageConverter rocketMQMessageConverter, + public ListenerContainerConfiguration(RocketMQMessageConverter rocketMQMessageConverter, StandardEnvironment environment, RocketMQProperties rocketMQProperties) { - this.objectMapper = rocketMQMessageObjectMapper; this.rocketMQMessageConverter = rocketMQMessageConverter; this.environment = environment; this.rocketMQProperties = rocketMQProperties; @@ -145,7 +141,6 @@ private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String } container.setConsumerGroup(environment.resolvePlaceholders(annotation.consumerGroup())); container.setRocketMQListener((RocketMQListener)bean); - container.setObjectMapper(objectMapper); container.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); container.setName(name); // REVIEW ME, use the same clientId or multiple? diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java index f4abf723..8d63e92a 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java @@ -17,7 +17,6 @@ package org.apache.rocketmq.spring.autoconfigure; -import com.fasterxml.jackson.databind.ObjectMapper; import java.lang.reflect.Field; import javax.annotation.PostConstruct; import org.apache.rocketmq.acl.common.AclClientRPCHook; @@ -53,10 +52,10 @@ @Configuration @EnableConfigurationProperties(RocketMQProperties.class) -@ConditionalOnClass({MQAdmin.class, ObjectMapper.class}) +@ConditionalOnClass({MQAdmin.class}) @ConditionalOnProperty(prefix = "rocketmq", value = "name-server", matchIfMissing = true) -@Import({JacksonFallbackConfiguration.class, MessageConverterConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class}) -@AutoConfigureAfter({JacksonFallbackConfiguration.class, MessageConverterConfiguration.class}) +@Import({MessageConverterConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class}) +@AutoConfigureAfter({MessageConverterConfiguration.class}) public class RocketMQAutoConfiguration { private static final Logger log = LoggerFactory.getLogger(RocketMQAutoConfiguration.class); @@ -127,11 +126,9 @@ public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties @ConditionalOnBean(DefaultMQProducer.class) @ConditionalOnMissingBean(name = RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, - ObjectMapper rocketMQMessageObjectMapper, RocketMQMessageConverter rocketMQMessageConverter) { RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); rocketMQTemplate.setProducer(mqProducer); - rocketMQTemplate.setObjectMapper(rocketMQMessageObjectMapper); rocketMQTemplate.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); return rocketMQTemplate; } 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 dd341558..1072b764 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 @@ -17,7 +17,6 @@ package org.apache.rocketmq.spring.core; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.Collection; import java.util.Map; @@ -48,9 +47,6 @@ public class RocketMQTemplate extends AbstractMessageSendingTemplate imp private DefaultMQProducer producer; - @Deprecated - private ObjectMapper objectMapper; - private String charset = "UTF-8"; private MessageQueueSelector messageQueueSelector = new SelectMessageQueueByHash(); @@ -63,16 +59,6 @@ public void setProducer(DefaultMQProducer producer) { this.producer = producer; } - @Deprecated - public ObjectMapper getObjectMapper() { - return objectMapper; - } - - @Deprecated - public void setObjectMapper(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; - } - public String getCharset() { return charset; } 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 c9248641..2d8a043a 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 @@ -17,7 +17,6 @@ package org.apache.rocketmq.spring.support; -import com.fasterxml.jackson.databind.ObjectMapper; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.nio.charset.Charset; @@ -86,9 +85,6 @@ public class DefaultRocketMQListenerContainer implements InitializingBean, private String charset = "UTF-8"; - @Deprecated - private ObjectMapper objectMapper; - private MessageConverter messageConverter; private RocketMQListener rocketMQListener; @@ -168,16 +164,6 @@ public void setCharset(String charset) { this.charset = charset; } - @Deprecated - public ObjectMapper getObjectMapper() { - return objectMapper; - } - - @Deprecated - public void setObjectMapper(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; - } - public MessageConverter getMessageConverter() { return messageConverter; } diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index c2e9ad9c..a359c637 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -91,7 +91,6 @@ public void testDefaultMQProducer() { run((context) -> { assertThat(context).hasSingleBean(DefaultMQProducer.class); }); - } @Test @@ -140,7 +139,6 @@ public void testRocketMQTransactionListener() { assertThat(context).hasSingleBean(TestRocketMQLocalTransactionListener.class); }); - } @Test From 17d3779606fb7d56b43f6aad320f92eaaebae365 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 6 Dec 2019 16:57:43 +0800 Subject: [PATCH 038/105] chore(test):upgrade rocketmq version to 4.6.0 and add unit tests --- rocketmq-spring-boot-parent/pom.xml | 2 +- .../RocketMQAutoConfigurationTest.java | 192 ++++++++---------- .../spring/core/RocketMQTemplateTest.java | 50 +++++ .../DefaultRocketMQListenerContainerTest.java | 7 +- .../spring/support/RocketMQUtilTest.java | 60 +++++- 5 files changed, 196 insertions(+), 115 deletions(-) create mode 100644 rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index 8352241a..ca490b01 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -40,7 +40,7 @@ 2.0.5-SNAPSHOT - 4.5.2 + 4.6.0 1.7.25 2.9.7 diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index c2e9ad9c..553183d1 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -17,10 +17,10 @@ package org.apache.rocketmq.spring.autoconfigure; -import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.ArrayList; +import java.util.List; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.SendResult; -import org.apache.rocketmq.client.producer.SendStatus; import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; @@ -28,7 +28,6 @@ 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.DefaultRocketMQListenerContainer; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.junit.Assert; import org.junit.Test; @@ -41,18 +40,13 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.Message; -import org.springframework.messaging.MessagingException; import org.springframework.messaging.support.GenericMessage; -import java.util.ArrayList; -import java.util.List; - import static org.assertj.core.api.Assertions.assertThat; public class RocketMQAutoConfigurationTest { private ApplicationContextRunner runner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(RocketMQAutoConfiguration.class)); - + .withConfiguration(AutoConfigurations.of(RocketMQAutoConfiguration.class)); @Test(expected = NoSuchBeanDefinitionException.class) public void testDefaultMQProducerNotCreatedByDefault() { @@ -60,128 +54,133 @@ public void testDefaultMQProducerNotCreatedByDefault() { runner.run(context -> context.getBean(DefaultMQProducer.class)); } - @Test public void testDefaultMQProducerWithRelaxPropertyName() { runner.withPropertyValues("rocketmq.nameServer=127.0.0.1:9876", - "rocketmq.producer.group=spring_rocketmq", - "rocketmq.accessChannel=LOCAL"). - run((context) -> { - assertThat(context).hasSingleBean(DefaultMQProducer.class); - assertThat(context).hasSingleBean(RocketMQProperties.class); - }); + "rocketmq.producer.group=spring_rocketmq", + "rocketmq.accessChannel=LOCAL"). + run((context) -> { + assertThat(context).hasSingleBean(DefaultMQProducer.class); + assertThat(context).hasSingleBean(RocketMQProperties.class); + }); } @Test public void testBadAccessChannelProperty() { runner.withPropertyValues("rocketmq.nameServer=127.0.0.1:9876", - "rocketmq.producer.group=spring_rocketmq", - "rocketmq.accessChannel=LOCAL123"). - run((context) -> { - //Should throw exception for bad accessChannel property - assertThat(context).getFailure(); - }); + "rocketmq.producer.group=spring_rocketmq", + "rocketmq.accessChannel=LOCAL123"). + run((context) -> { + //Should throw exception for bad accessChannel property + assertThat(context).getFailure(); + }); } @Test public void testDefaultMQProducer() { runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", - "rocketmq.producer.group=spring_rocketmq"). - run((context) -> { - assertThat(context).hasSingleBean(DefaultMQProducer.class); - }); - + "rocketmq.producer.group=spring_rocketmq"). + run((context) -> { + assertThat(context).hasSingleBean(DefaultMQProducer.class); + }); } @Test public void testExtRocketMQTemplate() { runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). - withUserConfiguration(TestExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). - run(new ContextConsumer() { - @Override - public void accept(AssertableApplicationContext context) throws Throwable { - Throwable th = context.getStartupFailure(); - System.out.printf("th==" + th + "\n"); - Assert.assertTrue(th instanceof BeanDefinitionValidationException); - } - }); + withUserConfiguration(TestExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). + run(new ContextConsumer() { + @Override + public void accept(AssertableApplicationContext context) throws Throwable { + Throwable th = context.getStartupFailure(); + System.out.printf("th==" + th + "\n"); + Assert.assertTrue(th instanceof BeanDefinitionValidationException); + } + }); runner.withPropertyValues("rocketmq.name-server=127.0.1.1:9876"). - withUserConfiguration(TestExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). - run((context) -> { - // No producer on consume side - assertThat(context).getBean("extRocketMQTemplate").hasFieldOrProperty("producer"); - // Auto-create consume container if existing Bean annotated with @RocketMQMessageListener - }); + withUserConfiguration(TestExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). + run((context) -> { + // No producer on consume side + assertThat(context).getBean("extRocketMQTemplate").hasFieldOrProperty("producer"); + // Auto-create consume container if existing Bean annotated with @RocketMQMessageListener + }); } @Test public void testConsumerListener() { runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", - "rocketmq.producer.group=spring_rocketmq", - "rocketmq.consumer.listeners.spring_rocketmq.FOO_TEST_TOPIC=false", - "rocketmq.consumer.listeners.spring_rocketmq.FOO_TEST_TOPIC2=true"). - run((context) -> { - RocketMQProperties rocketMQProperties = context.getBean(RocketMQProperties.class); - assertThat(rocketMQProperties.getConsumer().getListeners().get("spring_rocketmq").get("FOO_TEST_TOPIC").booleanValue()).isEqualTo(false); - assertThat(rocketMQProperties.getConsumer().getListeners().get("spring_rocketmq").get("FOO_TEST_TOPIC2").booleanValue()).isEqualTo(true); - }); + "rocketmq.producer.group=spring_rocketmq", + "rocketmq.consumer.listeners.spring_rocketmq.FOO_TEST_TOPIC=false", + "rocketmq.consumer.listeners.spring_rocketmq.FOO_TEST_TOPIC2=true"). + run((context) -> { + RocketMQProperties rocketMQProperties = context.getBean(RocketMQProperties.class); + assertThat(rocketMQProperties.getConsumer().getListeners().get("spring_rocketmq").get("FOO_TEST_TOPIC").booleanValue()).isEqualTo(false); + assertThat(rocketMQProperties.getConsumer().getListeners().get("spring_rocketmq").get("FOO_TEST_TOPIC2").booleanValue()).isEqualTo(true); + }); } @Test public void testRocketMQTransactionListener() { runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", - "rocketmq.producer.group=spring_rocketmq", - "demo.rocketmq.transaction.producer.group=transaction-group1"). - withUserConfiguration(TestTransactionListenerConfig.class). - run((context) -> { - assertThat(context).hasSingleBean(TestRocketMQLocalTransactionListener.class); - - }); - + "rocketmq.producer.group=spring_rocketmq", + "demo.rocketmq.transaction.producer.group=transaction-group1"). + withUserConfiguration(TestTransactionListenerConfig.class). + run((context) -> { + assertThat(context).hasSingleBean(TestRocketMQLocalTransactionListener.class); + }); } @Test public void testBatchSendMessage() { runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", - "rocketmq.producer.group=spring_rocketmq"). - run((context) -> { - RocketMQTemplate rocketMQTemplate = context.getBean(RocketMQTemplate.class); - List> batchMessages = new ArrayList>(); - - String errorMsg = null; - try { - SendResult customSendResult = rocketMQTemplate.syncSend("test", batchMessages, 60000); - } catch (IllegalArgumentException e) { - // it will be throw IllegalArgumentException: `messages` can not be empty - errorMsg = e.getMessage(); - } - - // that means the rocketMQTemplate.syncSend is chosen the correct type method - Assert.assertEquals("`messages` can not be empty", errorMsg); - }); + "rocketmq.producer.group=spring_rocketmq"). + run((context) -> { + RocketMQTemplate rocketMQTemplate = context.getBean(RocketMQTemplate.class); + List> batchMessages = new ArrayList>(); + + String errorMsg = null; + try { + SendResult customSendResult = rocketMQTemplate.syncSend("test", batchMessages, 60000); + } catch (IllegalArgumentException e) { + // it will be throw IllegalArgumentException: `messages` can not be empty + errorMsg = e.getMessage(); + } + + // that means the rocketMQTemplate.syncSend is chosen the correct type method + Assert.assertEquals("`messages` can not be empty", errorMsg); + }); } public void testPlaceholdersListenerContainer() { runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", - "demo.placeholders.consumer.group = abc3", - "demo.placeholders.consumer.topic = test", - "demo.placeholders.consumer.tags = tag1"). - withUserConfiguration(TestPlaceholdersConfig.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).hasBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1"); - assertThat(context).getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1"). - hasFieldOrPropertyWithValue("nameServer", "127.0.0.1:9876"). - hasFieldOrPropertyWithValue("consumerGroup", "abc3"). - hasFieldOrPropertyWithValue("topic", "test"). - hasFieldOrPropertyWithValue("selectorExpression", "tag1"); - }); + "demo.placeholders.consumer.group = abc3", + "demo.placeholders.consumer.topic = test", + "demo.placeholders.consumer.tags = tag1"). + withUserConfiguration(TestPlaceholdersConfig.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).hasBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1"); + assertThat(context).getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1"). + hasFieldOrPropertyWithValue("nameServer", "127.0.0.1:9876"). + hasFieldOrPropertyWithValue("consumerGroup", "abc3"). + hasFieldOrPropertyWithValue("topic", "test"). + hasFieldOrPropertyWithValue("selectorExpression", "tag1"); + }); + } + + @Test + public void testRocketMQListenerContainer() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). + withUserConfiguration(TestConfig.class). + run((context) -> { + assertThat(context).getFailure().hasMessageContaining("connect to [127.0.0.1:9876] failed"); + }); } @Configuration @@ -202,30 +201,16 @@ public Object consumeListener1() { @Configuration static class CustomObjectMapperConfig { - @Bean - public ObjectMapper testObjectMapper() { - return new ObjectMapper(); - } @Bean public RocketMQMessageConverter rocketMQMessageConverter() { return new RocketMQMessageConverter(); } - } @Configuration static class CustomObjectMappersConfig { - @Bean - public ObjectMapper testObjectMapper() { - return new ObjectMapper(); - } - - @Bean - public ObjectMapper rocketMQMessageObjectMapper() { - return new ObjectMapper(); - } @Bean public RocketMQMessageConverter rocketMQMessageConverter() { return new RocketMQMessageConverter(); @@ -263,7 +248,6 @@ public Object rocketMQLocalTransactionListener() { @RocketMQTransactionListener static class TestRocketMQLocalTransactionListener implements RocketMQLocalTransactionListener { - @Override public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { return RocketMQLocalTransactionState.COMMIT; diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java new file mode 100644 index 00000000..af2d6367 --- /dev/null +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java @@ -0,0 +1,50 @@ +package org.apache.rocketmq.spring.core; + +import javax.annotation.Resource; +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.messaging.MessagingException; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(properties = {"rocketmq.nameServer=127.0.0.1:9876", "rocketmq.producer.group=producer_group"}, classes = RocketMQAutoConfiguration.class) + +public class RocketMQTemplateTest { + @Resource + RocketMQTemplate rocketMQTemplate; + + @Test + public void testSendMessage() { + try { + rocketMQTemplate.syncSend("test", "123"); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); + } + + try { + rocketMQTemplate.asyncSend("test", "123", new SendCallback() { + @Override public void onSuccess(SendResult sendResult) { + + } + + @Override public void onException(Throwable e) { + + } + }); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); + } + + try { + rocketMQTemplate.syncSendOrderly("test", "123", "123"); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); + } + } +} 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 ea85b98d..6395c9e5 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 @@ -16,11 +16,10 @@ */ package org.apache.rocketmq.spring.support; +import java.lang.reflect.Method; 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; @@ -36,7 +35,7 @@ public void testGetMessageType() throws Exception { public void onMessage(String message) { } }); - Class result = (Class)getMessageType.invoke(listenerContainer); + Class result = (Class) getMessageType.invoke(listenerContainer); assertThat(result.getName().equals(String.class.getName())); listenerContainer.setRocketMQListener(new RocketMQListener() { @@ -44,7 +43,7 @@ public void onMessage(String message) { public void onMessage(MessageExt message) { } }); - result = (Class)getMessageType.invoke(listenerContainer); + result = (Class) getMessageType.invoke(listenerContainer); assertThat(result.getName().equals(MessageExt.class.getName())); } } 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 index 3a0bc41b..94cf07a6 100644 --- 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 @@ -17,13 +17,19 @@ package org.apache.rocketmq.spring.support; import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Arrays; +import org.apache.rocketmq.acl.common.AclClientRPCHook; +import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.remoting.RPCHook; import org.junit.Test; import org.springframework.messaging.Message; import org.springframework.messaging.support.MessageBuilder; -import java.util.Arrays; - -import static org.junit.Assert.*; +import static org.apache.rocketmq.spring.support.RocketMQUtil.toRocketHeaderKey; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; public class RocketMQUtilTest { @@ -52,8 +58,8 @@ public void testPayload() { org.apache.rocketmq.common.message.Message rocketMsg2 = RocketMQUtil.convertToRocketMessage(objectMapper, charset, destination, msgWithBytePayload); - assertTrue(Arrays.equals(((String)msgWithStringPayload.getPayload()).getBytes(), rocketMsg1.getBody())); - assertTrue(Arrays.equals((byte[])msgWithBytePayload.getPayload(), rocketMsg2.getBody())); + assertTrue(Arrays.equals(((String) msgWithStringPayload.getPayload()).getBytes(), rocketMsg1.getBody())); + assertTrue(Arrays.equals((byte[]) msgWithBytePayload.getPayload(), rocketMsg2.getBody())); } @Test @@ -87,9 +93,51 @@ public void testHeaderConvertToSpringMsg() { assertEquals(String.valueOf("tags"), rocketMsg.getProperty(RocketMQHeaders.PREFIX + RocketMQHeaders.TAGS)); assertNull(rocketMsg.getTags()); - rmqMsg.putUserProperty(RocketMQUtil.toRocketHeaderKey(RocketMQHeaders.TAGS), "tags2"); + rmqMsg.putUserProperty(toRocketHeaderKey(RocketMQHeaders.TAGS), "tags2"); springMsg = RocketMQUtil.convertToSpringMessage(rmqMsg); assertEquals("tags", springMsg.getHeaders().get(RocketMQHeaders.PREFIX + RocketMQHeaders.TAGS)); } + @Test + public void testConvertToRocketMessageWithMessageConvert() { + Message msgWithStringPayload = MessageBuilder.withPayload("test body") + .setHeader("test", 1) + .setHeader(RocketMQHeaders.TAGS, "tags") + .setHeader(RocketMQHeaders.KEYS, "my_keys") + .build(); + RocketMQMessageConverter messageConverter = new RocketMQMessageConverter(); + org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(messageConverter.getMessageConverter(), + "UTF-8", "test-topic", msgWithStringPayload); + assertEquals("1", rocketMsg.getProperty("test")); + assertNull(rocketMsg.getProperty(RocketMQHeaders.TAGS)); + assertEquals("my_keys", rocketMsg.getProperty(RocketMQHeaders.KEYS)); + + Message msgWithBytesPayload = MessageBuilder.withPayload("123".getBytes()).build(); + org.apache.rocketmq.common.message.Message rocketMsgWithObj = RocketMQUtil.convertToRocketMessage(messageConverter.getMessageConverter(), + "UTF-8", "test-topic", msgWithBytesPayload); + assertEquals("123", new String(rocketMsgWithObj.getBody())); + } + + @Test + public void testConvertToSpringMessage() { + org.apache.rocketmq.common.message.MessageExt rocketMsg = new org.apache.rocketmq.common.message.MessageExt(); + rocketMsg.setTopic("test"); + rocketMsg.setBody("123".getBytes()); + rocketMsg.setTags("tagA"); + rocketMsg.setKeys("key1"); + Message message = RocketMQUtil.convertToSpringMessage(rocketMsg); + assertEquals("test", message.getHeaders().get(toRocketHeaderKey(RocketMQHeaders.TOPIC))); + assertEquals("tagA", message.getHeaders().get(toRocketHeaderKey(RocketMQHeaders.TAGS))); + assertEquals("key1", message.getHeaders().get(toRocketHeaderKey(RocketMQHeaders.KEYS))); + } + + @Test + public void testGetInstanceName() { + String ak = "123"; + String sk = "456"; + String consumerGroup = "consumerGroup"; + RPCHook rpcHook = new AclClientRPCHook(new SessionCredentials(ak, sk)); + String expected = "123|456|consumerGroup|"; + assertEquals(expected + UtilAll.getPid(), RocketMQUtil.getInstanceName(rpcHook, consumerGroup)); + } } \ No newline at end of file From 075f41d37c5b02c015981996b67fb3268a3c3293 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 6 Dec 2019 17:02:40 +0800 Subject: [PATCH 039/105] chore(autoconfig):delete useless code --- .../spring/support/RocketMQMessageConverter.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java index c2ee1daf..a6f0af91 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java @@ -75,20 +75,4 @@ public MessageConverter getMessageConverter() { return messageConverter; } - public MessageConverter resetMessageConverter( - Collection converters) { - if (messageConverter.getConverters() != null) { - messageConverter.getConverters().clear(); - } - Objects.requireNonNull(messageConverter.getConverters()).addAll(converters); - return messageConverter; - } - - public MessageConverter addMessageConverter(MessageConverter converter) { - if (messageConverter.getConverters() != null && converter != null) { - messageConverter.getConverters().add(converter); - } - return messageConverter; - } - } From e40bf990a7ca9c611f6edd4d3adb9517dcdc340f Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 6 Dec 2019 17:08:58 +0800 Subject: [PATCH 040/105] chore(autoconfig):pass checkstyle --- .../rocketmq/spring/support/RocketMQMessageConverter.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java index a6f0af91..51a67193 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQMessageConverter.java @@ -18,10 +18,7 @@ package org.apache.rocketmq.spring.support; import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import java.util.Objects; - import org.springframework.messaging.converter.ByteArrayMessageConverter; import org.springframework.messaging.converter.CompositeMessageConverter; import org.springframework.messaging.converter.MappingJackson2MessageConverter; From 228ebf1444cd4231c177543af0398dd386606bbd Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 6 Dec 2019 20:00:37 +0800 Subject: [PATCH 041/105] chore(test):polish code --- .../apache/rocketmq/spring/core/RocketMQTemplateTest.java | 6 +++--- .../apache/rocketmq/spring/support/RocketMQUtilTest.java | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java index af2d6367..55fcca38 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java @@ -22,13 +22,13 @@ public class RocketMQTemplateTest { @Test public void testSendMessage() { try { - rocketMQTemplate.syncSend("test", "123"); + rocketMQTemplate.syncSend("test", "payload"); } catch (MessagingException e) { assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); } try { - rocketMQTemplate.asyncSend("test", "123", new SendCallback() { + rocketMQTemplate.asyncSend("test", "payload", new SendCallback() { @Override public void onSuccess(SendResult sendResult) { } @@ -42,7 +42,7 @@ public void testSendMessage() { } try { - rocketMQTemplate.syncSendOrderly("test", "123", "123"); + rocketMQTemplate.syncSendOrderly("test", "payload", "hashkey"); } catch (MessagingException e) { assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); } 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 index 94cf07a6..41b09226 100644 --- 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 @@ -122,7 +122,7 @@ public void testConvertToRocketMessageWithMessageConvert() { public void testConvertToSpringMessage() { org.apache.rocketmq.common.message.MessageExt rocketMsg = new org.apache.rocketmq.common.message.MessageExt(); rocketMsg.setTopic("test"); - rocketMsg.setBody("123".getBytes()); + rocketMsg.setBody("test".getBytes()); rocketMsg.setTags("tagA"); rocketMsg.setKeys("key1"); Message message = RocketMQUtil.convertToSpringMessage(rocketMsg); @@ -133,11 +133,11 @@ public void testConvertToSpringMessage() { @Test public void testGetInstanceName() { - String ak = "123"; - String sk = "456"; + String ak = "ak"; + String sk = "sk"; String consumerGroup = "consumerGroup"; RPCHook rpcHook = new AclClientRPCHook(new SessionCredentials(ak, sk)); - String expected = "123|456|consumerGroup|"; + String expected = "ak|sk|consumerGroup|"; assertEquals(expected + UtilAll.getPid(), RocketMQUtil.getInstanceName(rpcHook, consumerGroup)); } } \ No newline at end of file From c8a34fab6a42ac9393b7882e79a91fa198eef79d Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 6 Dec 2019 20:07:50 +0800 Subject: [PATCH 042/105] chore(test):add ASF header --- .../spring/core/RocketMQTemplateTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java index 55fcca38..0b88a751 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java @@ -1,3 +1,19 @@ +/* + * 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 javax.annotation.Resource; From 5f767baf11a9b00e37bd5eda3efad6827911e8e9 Mon Sep 17 00:00:00 2001 From: caimofei Date: Wed, 11 Dec 2019 16:42:47 +0800 Subject: [PATCH 043/105] solve the program that rocketMqListener can not support generic parameter --- .../DefaultRocketMQListenerContainer.java | 89 +++++++++++++------ 1 file changed, 60 insertions(+), 29 deletions(-) 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 2d8a043a..f03a3e28 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 @@ -17,20 +17,11 @@ package org.apache.rocketmq.spring.support; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.nio.charset.Charset; -import java.util.List; -import java.util.Objects; +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.rocketmq.client.AccessChannel; 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.consumer.listener.*; import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.common.message.MessageExt; @@ -49,13 +40,22 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.SmartLifecycle; +import org.springframework.core.MethodParameter; import org.springframework.messaging.converter.MessageConverter; +import org.springframework.messaging.converter.SmartMessageConverter; import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.Assert; +import java.lang.reflect.Method; +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, ApplicationContextAware { + RocketMQListenerContainer, SmartLifecycle, ApplicationContextAware { private final static Logger log = LoggerFactory.getLogger(DefaultRocketMQListenerContainer.class); private ApplicationContext applicationContext; @@ -93,7 +93,9 @@ public class DefaultRocketMQListenerContainer implements InitializingBean, private DefaultMQPushConsumer consumer; - private Class messageType; + private Type messageType; + + private MethodParameter methodParameter; private boolean running; @@ -297,7 +299,8 @@ public void afterPropertiesSet() throws Exception { initRocketMQPushConsumer(); this.messageType = getMessageType(); - log.debug("RocketMQ messageType: {}", messageType.getName()); + this.methodParameter = getMethodParameter(); + log.debug("RocketMQ messageType: {}", messageType); } @Override @@ -308,14 +311,14 @@ public void setApplicationContext(ApplicationContext applicationContext) throws @Override public String toString() { return "DefaultRocketMQListenerContainer{" + - "consumerGroup='" + consumerGroup + '\'' + - ", nameServer='" + nameServer + '\'' + - ", topic='" + topic + '\'' + - ", consumeMode=" + consumeMode + - ", selectorType=" + selectorType + - ", selectorExpression='" + selectorExpression + '\'' + - ", messageModel=" + messageModel + - '}'; + "consumerGroup='" + consumerGroup + '\'' + + ", nameServer='" + nameServer + '\'' + + ", topic='" + topic + '\'' + + ", consumeMode=" + consumeMode + + ", selectorType=" + selectorType + + ", selectorExpression='" + selectorExpression + '\'' + + ", messageModel=" + messageModel + + '}'; } public void setName(String name) { @@ -380,7 +383,14 @@ private Object doConvertMessage(MessageExt messageExt) { } else { // If msgType not string, use objectMapper change it. try { - return this.getMessageConverter().fromMessage(MessageBuilder.withPayload(str).build(), messageType); + if (messageType instanceof Class) { + //if the messageType is has not Generic Parameter + return this.getMessageConverter().fromMessage(MessageBuilder.withPayload(str).build(), (Class) messageType); + } else { + //if the messageType has Generic Parameter, then use SmartMessageConverter#fromMessage with third parameter "conversionHint". + //we have validate the MessageConverter is SmartMessageConverter in this#getMethodParameter. + return ((SmartMessageConverter) this.getMessageConverter()).fromMessage(MessageBuilder.withPayload(str).build(), (Class) ((ParameterizedType) messageType).getRawType(), methodParameter); + } } catch (Exception e) { log.info("convert failed. str:{}, msgType:{}", str, messageType); throw new RuntimeException("cannot convert message to " + messageType, e); @@ -389,7 +399,28 @@ private Object doConvertMessage(MessageExt messageExt) { } } - private Class getMessageType() { + + private MethodParameter getMethodParameter() { + Class targetClass = AopProxyUtils.ultimateTargetClass(rocketMQListener); + Type messageType = this.messageType; + Class clazz = null; + if (messageType instanceof ParameterizedType && messageConverter instanceof SmartMessageConverter) { + clazz = (Class) ((ParameterizedType) messageType).getRawType(); + } else if (messageType instanceof Class) { + clazz = (Class) messageType; + } else { + throw new RuntimeException("parameterType:" + messageType + " of onMessage method is not supported"); + } + try { + final Method method = targetClass.getMethod("onMessage", clazz); + return new MethodParameter(method, 0); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + throw new RuntimeException("parameterType:" + messageType + " of onMessage method is not supported"); + } + } + + private Type getMessageType() { Class targetClass = AopProxyUtils.ultimateTargetClass(rocketMQListener); Type[] interfaces = targetClass.getGenericInterfaces(); Class superclass = targetClass.getSuperclass(); @@ -404,7 +435,7 @@ private Class getMessageType() { if (Objects.equals(parameterizedType.getRawType(), RocketMQListener.class)) { Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) { - return (Class) actualTypeArguments[0]; + return actualTypeArguments[0]; } else { return Object.class; } @@ -425,19 +456,19 @@ private void initRocketMQPushConsumer() throws MQClientException { Assert.notNull(topic, "Property 'topic' is required"); RPCHook rpcHook = RocketMQUtil.getRPCHookByAkSk(applicationContext.getEnvironment(), - this.rocketMQMessageListener.accessKey(), this.rocketMQMessageListener.secretKey()); + this.rocketMQMessageListener.accessKey(), this.rocketMQMessageListener.secretKey()); boolean enableMsgTrace = rocketMQMessageListener.enableMsgTrace(); if (Objects.nonNull(rpcHook)) { consumer = new DefaultMQPushConsumer(consumerGroup, rpcHook, new AllocateMessageQueueAveragely(), - enableMsgTrace, this.applicationContext.getEnvironment(). - resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); + enableMsgTrace, this.applicationContext.getEnvironment(). + resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); consumer.setVipChannelEnabled(false); consumer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, consumerGroup)); } else { log.debug("Access-key or secret-key not configure in " + this + "."); consumer = new DefaultMQPushConsumer(consumerGroup, enableMsgTrace, this.applicationContext.getEnvironment(). - resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); + resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); } String customizedNameServer = this.applicationContext.getEnvironment().resolveRequiredPlaceholders(this.rocketMQMessageListener.nameServer()); From acca45028ba81402065afe3f23738dbe445e94b2 Mon Sep 17 00:00:00 2001 From: caimofei Date: Wed, 11 Dec 2019 17:10:34 +0800 Subject: [PATCH 044/105] solve the program that rocketMqListener can not support generic parameter --- .../DefaultRocketMQListenerContainer.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) 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 f03a3e28..2561c61b 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 @@ -17,11 +17,21 @@ package org.apache.rocketmq.spring.support; -import com.fasterxml.jackson.databind.ObjectMapper; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Objects; import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.MessageSelector; -import org.apache.rocketmq.client.consumer.listener.*; +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.consumer.rebalance.AllocateMessageQueueAveragely; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.common.message.MessageExt; @@ -46,13 +56,6 @@ import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.Assert; -import java.lang.reflect.Method; -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, ApplicationContextAware { From 948ab3840eb935003828a5d751d9fda8208de63c Mon Sep 17 00:00:00 2001 From: caimofei Date: Wed, 11 Dec 2019 17:56:54 +0800 Subject: [PATCH 045/105] solve the program that rocketMqListener can not support generic parameter --- .../DefaultRocketMQListenerContainer.java | 2 +- .../DefaultRocketMQListenerContainerTest.java | 33 ++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) 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 2561c61b..2f39859c 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 @@ -405,7 +405,7 @@ private Object doConvertMessage(MessageExt messageExt) { private MethodParameter getMethodParameter() { Class targetClass = AopProxyUtils.ultimateTargetClass(rocketMQListener); - Type messageType = this.messageType; + Type messageType = this.getMessageType(); Class clazz = null; if (messageType instanceof ParameterizedType && messageConverter instanceof SmartMessageConverter) { clazz = (Class) ((ParameterizedType) messageType).getRawType(); 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 6395c9e5..e95698ea 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 @@ -16,10 +16,19 @@ */ package org.apache.rocketmq.spring.support; -import java.lang.reflect.Method; import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.spring.core.RocketMQListener; import org.junit.Test; +import org.springframework.core.MethodParameter; +import org.springframework.messaging.converter.CompositeMessageConverter; +import org.springframework.messaging.converter.MappingJackson2MessageConverter; +import org.springframework.messaging.converter.StringMessageConverter; + +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; import static org.assertj.core.api.Assertions.assertThat; @@ -46,6 +55,28 @@ public void onMessage(MessageExt message) { result = (Class) getMessageType.invoke(listenerContainer); assertThat(result.getName().equals(MessageExt.class.getName())); } + + @Test + public void testGenericMessageType() throws Exception { + DefaultRocketMQListenerContainer listenerContainer = new DefaultRocketMQListenerContainer(); + listenerContainer.setMessageConverter(new CompositeMessageConverter(Arrays.asList(new StringMessageConverter(), new MappingJackson2MessageConverter()))); + + Method getMessageType = DefaultRocketMQListenerContainer.class.getDeclaredMethod("getMessageType"); + Method getMethodParameter = DefaultRocketMQListenerContainer.class.getDeclaredMethod("getMethodParameter"); + getMessageType.setAccessible(true); + getMethodParameter.setAccessible(true); + listenerContainer.setRocketMQListener(new RocketMQListener>() { + @Override + public void onMessage(ArrayList message) { + + } + }); + + ParameterizedType type = (ParameterizedType) getMessageType.invoke(listenerContainer); + assertThat(type.getRawType() == ArrayList.class); + MethodParameter methodParameter = ((MethodParameter) getMethodParameter.invoke(listenerContainer)); + System.out.println(methodParameter); + } } From eeb592c44f86369ae3b01f26ee8385d29a4d3bd9 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Thu, 12 Dec 2019 11:29:28 +0800 Subject: [PATCH 046/105] doc(readme):polish readme doc --- README.md | 403 ++++-------------------------------------------------- 1 file changed, 27 insertions(+), 376 deletions(-) diff --git a/README.md b/README.md index 04a9334e..210147d0 100644 --- a/README.md +++ b/README.md @@ -4,47 +4,32 @@ [![GitHub release](https://img.shields.io/badge/release-download-orange.svg)](https://github.com/apache/rocketmq-spring/releases) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) -[中文](./README_zh_CN.md) - -## Introduction - 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 - -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/) - +## Features + +- [x] Send messages synchronously +- [x] Send messages asynchronously +- [x] Send messages in one-way mode +- [x] Send messages orderly +- [x] Send messages in batch +- [x] Send transactional messages +- [x] Send scheduled messages with delay level +- [x] Consume messages with concurrently mode (broadcasting/clustering) +- [x] Consume messages with orderly mode +- [x] Support message filter with tag and sql +- [x] Support message tracing capability +- [x] Authentication and authorisation +- [ ] Request-reply mode ## Prerequisites - JDK 1.8 and above - [Maven](http://maven.apache.org/) 3.0 and above +- Spring Boot 2.0 and above -## Build and Install with local maven repository - -``` - mvn clean install -``` - -## Features: +## Usage -- [x] synchronous transmission -- [x] synchronous ordered transmission -- [x] synchronous batch transmission -- [x] asynchronous transmission -- [x] asynchronous ordered transmission -- [x] orderly consume -- [x] concurrently consume(broadcasting/clustering) -- [x] one-way transmission -- [x] transaction transmission -- [x] message trace -- [x] ACL -- [ ] pull consume - -## Quick Start - -Please see the complete sample [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples) - -Note: Current RELEASE.VERSION=2.0.4 +Add a dependency using maven: ```xml @@ -53,354 +38,20 @@ Note: Current RELEASE.VERSION=2.0.4 rocketmq-spring-boot-starter ${RELEASE.VERSION} -``` - -### Produce Message - -```properties -## application.properties -rocketmq.name-server=127.0.0.1:9876 -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 -> rocketmq.producer.send-message-timeout=300000 -> rocketmq.producer.compress-message-body-threshold=4096 -> rocketmq.producer.max-message-size=4194304 -> rocketmq.producer.retry-times-when-send-async-failed=0 -> rocketmq.producer.retry-next-server=true -> rocketmq.producer.retry-times-when-send-failed=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 -rocketmq.name-server=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{ - 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{ - public void onMessage(OrderPaidEvent orderPaidEvent) { - log.info("received orderPaidEvent: {}", orderPaidEvent); - } - } -} -``` - -> More relevant configurations for consuming: -> -> see: [RocketMQMessageListener](rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQMessageListener.java) - -### Message Trace +``` -We need 2 more configurations for support message trace in producer. +## Samples -```properties -## application.properties -rocketmq.name-server=127.0.0.1:9876 -rocketmq.producer.group=my-group +Please see the [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples) -rocketmq.producer.enable-msg-trace=true -rocketmq.producer.customized-trace-topic=my-trace-topic -``` +## Document -The message trace in consumer should configure in `@RocketMQMessageListener`. +Please see the [wiki]() page -``` -@Service -@RocketMQMessageListener( - topic = "test-topic-1", - consumerGroup = "my-consumer_test-topic-1", - enableMsgTrace = true, - customizedTraceTopic = "my-trace-topic" -) -public class MyConsumer implements RocketMQListener { - ... -} -``` +## Contributing -> Note: -> -> Maybe you need change `127.0.0.1:9876` with your real NameServer address for RocketMQ - -> By default, the message track feature of Producer and Consumer is turned on and the trace-topic is RMQ_SYS_TRACE_TOPIC -> The topic of message trace can be configured with `rocketmq.consumer.customized-trace-topic` configuration item, not required to be configured in each `@RocketMQTransactionListener` - - -### ACL - -We need 2 more configurations for support ACL in producer. - -```properties -## application.properties -rocketmq.name-server=127.0.0.1:9876 -rocketmq.producer.group=my-group - -rocketmq.producer.access-key=AK -rocketmq.producer.secret-key=SK -``` -Transaction Message should configure AK/SK in `@RocketMQTransactionListener`. - -``` -@RocketMQTransactionListener( - txProducerGroup = "test, - accessKey = "AK", - secretKey = "SK" -) -class TransactionListenerImpl implements RocketMQLocalTransactionListener { - ... -} -``` - -> Note: -> -> You do not need to configure AK/SK for each `@RocketMQTransactionListener`, you could configure `rocketmq.producer.access-key` and `rocketmq.producer.secret-key` as default value - -The ACL feature in consumer should configure AK/SK in `@RocketMQMessageListener`. - -``` -@Service -@RocketMQMessageListener( - topic = "test-topic-1", - consumerGroup = "my-consumer_test-topic-1", - accessKey = "AK", - secretKey = "SK" -) -public class MyConsumer implements RocketMQListener { - ... -} -``` - -> Note: -> -> You do not need to configure AK/SK for each `@RocketMQMessageListener`, you could configure `rocketmq.consumer.access-key` and `rocketmq.consumer.secret-key` as default value - -## FAQ - -1. How to connected many `nameserver` on production environment? - - `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? - - 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{ - 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, 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. +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/) -1. How do I create more than one RocketMQTemplate with a different name-server or other specific properties? - ```java - // Step1. Define an extra RocketMQTemplate with required properties, note, the 'nameServer' property must be different from the value of global - // Spring configuration 'rocketmq.name-server', other properties are optionally defined, they will use the global configuration - // definition by default. - - // The RocketMQTemplate's Spring Bean name is 'extRocketMQTemplate', same with the simplified class name (Initials lowercase) - @ExtRocketMQTemplateConfiguration(nameServer="127.0.0.1:9876" - , ... // override other specific properties if needed - ) - public class ExtRocketMQTemplate extends RocketMQTemplate { - // keep the body empty - } - - - // Step2. Use the extra RocketMQTemplate. e.g. - @Resource(name = "extRocketMQTemplate") // Must define the name to qualify to extra-defined RocketMQTemplate bean. - private RocketMQTemplate extRocketMQTemplate; - // you can use the template as normal. - - ``` - -1. How do I create a consumer Listener with different name-server other than the global Spring configuration 'rocketmq.name-server' ? - ```java - @Service - @RocketMQMessageListener( - nameServer = "NEW-NAMESERVER-LIST", // define new nameServer list - topic = "test-topic-1", - consumerGroup = "my-consumer_test-topic-1", - enableMsgTrace = true, - customizedTraceTopic = "my-trace-topic" - ) - public class MyNameServerConsumer implements RocketMQListener { - ... - } - ``` +## License +[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) Copyright (C) Apache Software Foundation \ No newline at end of file From 81899b75700db5eafeecfd7ea7080b25c78e63bc Mon Sep 17 00:00:00 2001 From: caimofei Date: Thu, 12 Dec 2019 16:54:25 +0800 Subject: [PATCH 047/105] solve the problem that rocketMqListener can not support generic parameter --- .../DefaultRocketMQListenerContainer.java | 28 +++++++++---------- .../DefaultRocketMQListenerContainerTest.java | 6 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) 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 2f39859c..ad59bc99 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 @@ -58,7 +58,7 @@ @SuppressWarnings("WeakerAccess") public class DefaultRocketMQListenerContainer implements InitializingBean, - RocketMQListenerContainer, SmartLifecycle, ApplicationContextAware { + RocketMQListenerContainer, SmartLifecycle, ApplicationContextAware { private final static Logger log = LoggerFactory.getLogger(DefaultRocketMQListenerContainer.class); private ApplicationContext applicationContext; @@ -314,14 +314,14 @@ public void setApplicationContext(ApplicationContext applicationContext) throws @Override public String toString() { return "DefaultRocketMQListenerContainer{" + - "consumerGroup='" + consumerGroup + '\'' + - ", nameServer='" + nameServer + '\'' + - ", topic='" + topic + '\'' + - ", consumeMode=" + consumeMode + - ", selectorType=" + selectorType + - ", selectorExpression='" + selectorExpression + '\'' + - ", messageModel=" + messageModel + - '}'; + "consumerGroup='" + consumerGroup + '\'' + + ", nameServer='" + nameServer + '\'' + + ", topic='" + topic + '\'' + + ", consumeMode=" + consumeMode + + ", selectorType=" + selectorType + + ", selectorExpression='" + selectorExpression + '\'' + + ", messageModel=" + messageModel + + '}'; } public void setName(String name) { @@ -387,7 +387,7 @@ private Object doConvertMessage(MessageExt messageExt) { // If msgType not string, use objectMapper change it. try { if (messageType instanceof Class) { - //if the messageType is has not Generic Parameter + //if the messageType has not Generic Parameter return this.getMessageConverter().fromMessage(MessageBuilder.withPayload(str).build(), (Class) messageType); } else { //if the messageType has Generic Parameter, then use SmartMessageConverter#fromMessage with third parameter "conversionHint". @@ -459,19 +459,19 @@ private void initRocketMQPushConsumer() throws MQClientException { Assert.notNull(topic, "Property 'topic' is required"); RPCHook rpcHook = RocketMQUtil.getRPCHookByAkSk(applicationContext.getEnvironment(), - this.rocketMQMessageListener.accessKey(), this.rocketMQMessageListener.secretKey()); + this.rocketMQMessageListener.accessKey(), this.rocketMQMessageListener.secretKey()); boolean enableMsgTrace = rocketMQMessageListener.enableMsgTrace(); if (Objects.nonNull(rpcHook)) { consumer = new DefaultMQPushConsumer(consumerGroup, rpcHook, new AllocateMessageQueueAveragely(), - enableMsgTrace, this.applicationContext.getEnvironment(). - resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); + enableMsgTrace, this.applicationContext.getEnvironment(). + resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); consumer.setVipChannelEnabled(false); consumer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, consumerGroup)); } else { log.debug("Access-key or secret-key not configure in " + this + "."); consumer = new DefaultMQPushConsumer(consumerGroup, enableMsgTrace, this.applicationContext.getEnvironment(). - resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); + resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); } String customizedNameServer = this.applicationContext.getEnvironment().resolveRequiredPlaceholders(this.rocketMQMessageListener.nameServer()); 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 e95698ea..60014c9e 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 @@ -16,6 +16,8 @@ */ package org.apache.rocketmq.spring.support; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.spring.core.RocketMQListener; import org.junit.Test; @@ -24,8 +26,6 @@ import org.springframework.messaging.converter.MappingJackson2MessageConverter; import org.springframework.messaging.converter.StringMessageConverter; -import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -75,7 +75,7 @@ public void onMessage(ArrayList message) { ParameterizedType type = (ParameterizedType) getMessageType.invoke(listenerContainer); assertThat(type.getRawType() == ArrayList.class); MethodParameter methodParameter = ((MethodParameter) getMethodParameter.invoke(listenerContainer)); - System.out.println(methodParameter); + assertThat(methodParameter.getParameterType() == ArrayList.class); } } From f13659e02318e6a502ce42f3d9defe45293929f6 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 13 Dec 2019 15:48:20 +0800 Subject: [PATCH 048/105] enhancement(extRocketMQTemplate):refactor transaction auto configuration and enable extRocketMQTemplate send transactional messages --- .../RocketMQTransactionListener.java | 6 + .../ExtProducerResetConfiguration.java | 27 ++++- .../RocketMQAutoConfiguration.java | 25 ++-- .../RocketMQTransactionConfiguration.java | 75 ++++++++++++ .../spring/config/RocketMQConfigUtils.java | 32 ----- ...ocketMQTransactionAnnotationProcessor.java | 111 ------------------ .../spring/core/RocketMQTemplate.java | 4 + .../spring/core/ExtRocketMQTemplateTest.java | 99 ++++++++++++++++ .../spring/core/RocketMQTemplateTest.java | 51 +++++++- 9 files changed, 262 insertions(+), 168 deletions(-) create mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.java delete mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQConfigUtils.java delete mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQTransactionAnnotationProcessor.java create mode 100644 rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/ExtRocketMQTemplateTest.java 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 index c65ffc69..dac280f4 100644 --- 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 @@ -57,4 +57,10 @@ */ int blockingQueueSize() default 2000; + /** + * Set rocketMQTemplate bean name, the default is rocketMQTemplate. + * if use ExtRocketMQTemplate, can set ExtRocketMQTemplate bean name. + */ + String rocketMQTemplateBeanName() default "rocketMQTemplate"; + } diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index dcb76e9a..1c019bbf 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -17,12 +17,16 @@ package org.apache.rocketmq.spring.autoconfigure; +import java.lang.reflect.Field; import java.util.Map; import java.util.Objects; import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.client.trace.AsyncTraceDispatcher; +import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl; import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; @@ -117,12 +121,27 @@ private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annota String customizedTraceTopic = environment.resolvePlaceholders(annotation.customizedTraceTopic()); customizedTraceTopic = StringUtils.isEmpty(customizedTraceTopic) ? producerConfig.getCustomizedTraceTopic() : customizedTraceTopic; - if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { - producer = new DefaultMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk)), - annotation.enableMsgTrace(), customizedTraceTopic); + boolean isEnableAcl = !StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk); + + if (isEnableAcl) { + producer = new TransactionMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk))); producer.setVipChannelEnabled(false); } else { - producer = new DefaultMQProducer(groupName, annotation.enableMsgTrace(), customizedTraceTopic); + producer = new TransactionMQProducer(groupName); + } + + if (annotation.enableMsgTrace()) { + try { + AsyncTraceDispatcher dispatcher = new AsyncTraceDispatcher(customizedTraceTopic, isEnableAcl ? new AclClientRPCHook(new SessionCredentials(ak, sk)) : null); + dispatcher.setHostProducer(producer.getDefaultMQProducerImpl()); + Field field = DefaultMQProducer.class.getDeclaredField("traceDispatcher"); + field.setAccessible(true); + field.set(producer, dispatcher); + producer.getDefaultMQProducerImpl().registerSendMessageHook( + new SendMessageTraceHookImpl(dispatcher)); + } catch (Throwable e) { + log.error("system mqtrace hook init failed ,maybe can't send msg trace data"); + } } producer.setNamesrvAddr(nameServer); diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java index 8d63e92a..14f7160c 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java @@ -27,16 +27,13 @@ import org.apache.rocketmq.client.producer.TransactionMQProducer; import org.apache.rocketmq.client.trace.AsyncTraceDispatcher; import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl; -import org.apache.rocketmq.spring.config.RocketMQConfigUtils; -import org.apache.rocketmq.spring.config.RocketMQTransactionAnnotationProcessor; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -45,7 +42,6 @@ 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.core.env.Environment; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -54,11 +50,16 @@ @EnableConfigurationProperties(RocketMQProperties.class) @ConditionalOnClass({MQAdmin.class}) @ConditionalOnProperty(prefix = "rocketmq", value = "name-server", matchIfMissing = true) -@Import({MessageConverterConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class}) +@Import({MessageConverterConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class, RocketMQTransactionConfiguration.class}) @AutoConfigureAfter({MessageConverterConfiguration.class}) +@AutoConfigureBefore({RocketMQTransactionConfiguration.class}) + public class RocketMQAutoConfiguration { private static final Logger log = LoggerFactory.getLogger(RocketMQAutoConfiguration.class); + public static final String ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME = + "rocketMQTemplate"; + @Autowired private Environment environment; @@ -124,7 +125,7 @@ public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties @Bean(destroyMethod = "destroy") @ConditionalOnBean(DefaultMQProducer.class) - @ConditionalOnMissingBean(name = RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) + @ConditionalOnMissingBean(name = ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, RocketMQMessageConverter rocketMQMessageConverter) { RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); @@ -132,14 +133,4 @@ public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, rocketMQTemplate.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); return rocketMQTemplate; } - - - @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME) - @ConditionalOnBean(name = RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) - @Role(BeanDefinition.ROLE_INFRASTRUCTURE) - public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor( - @Qualifier(RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) RocketMQTemplate template) { - return new RocketMQTransactionAnnotationProcessor(template); - } - } diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.java new file mode 100644 index 00000000..1a897e51 --- /dev/null +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.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.autoconfigure; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.apache.rocketmq.spring.support.RocketMQUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.framework.AopProxyUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RocketMQTransactionConfiguration implements ApplicationContextAware, SmartInitializingSingleton { + + private final static Logger log = LoggerFactory.getLogger(RocketMQTransactionConfiguration.class); + + private ConfigurableApplicationContext applicationContext; + + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = (ConfigurableApplicationContext) applicationContext; + } + + @Override public void afterSingletonsInstantiated() { + Map beans = this.applicationContext.getBeansWithAnnotation(RocketMQTransactionListener.class); + + if (Objects.nonNull(beans)) { + beans.forEach(this::registerTransactionListener); + } + } + + private void registerTransactionListener(String beanName, Object bean) { + Class clazz = AopProxyUtils.ultimateTargetClass(bean); + + if (!RocketMQLocalTransactionListener.class.isAssignableFrom(bean.getClass())) { + throw new IllegalStateException(clazz + " is not instance of " + RocketMQLocalTransactionListener.class.getName()); + } + RocketMQTransactionListener annotation = clazz.getAnnotation(RocketMQTransactionListener.class); + RocketMQTemplate rocketMQTemplate = (RocketMQTemplate) applicationContext.getBean(annotation.rocketMQTemplateBeanName()); + if (((TransactionMQProducer) rocketMQTemplate.getProducer()).getTransactionListener() != null) { + throw new IllegalStateException(annotation.rocketMQTemplateBeanName() + " already exists RocketMQLocalTransactionListener"); + } + ((TransactionMQProducer) rocketMQTemplate.getProducer()).setExecutorService(new ThreadPoolExecutor(annotation.corePoolSize(), annotation.maximumPoolSize(), + annotation.keepAliveTime(), TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(annotation.blockingQueueSize()))); + ((TransactionMQProducer) rocketMQTemplate.getProducer()).setTransactionListener(RocketMQUtil.convert((RocketMQLocalTransactionListener) bean)); + log.debug("RocketMQLocalTransactionListener {} register to {} success", clazz.getName(), annotation.rocketMQTemplateBeanName()); + } +} 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 deleted file mode 100644 index 3e1c573d..00000000 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQConfigUtils.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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"; - - public static final String ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME = - "rocketMQTemplate"; -} 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 deleted file mode 100644 index 9008d2d2..00000000 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQTransactionAnnotationProcessor.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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 java.util.Collections; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import org.apache.rocketmq.client.exception.MQClientException; -import org.apache.rocketmq.client.producer.TransactionMQProducer; -import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; -import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; -import org.apache.rocketmq.spring.core.RocketMQTemplate; -import org.apache.rocketmq.spring.support.RocketMQUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.aop.support.AopUtils; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.core.Ordered; -import org.springframework.core.annotation.AnnotationUtils; - -public class RocketMQTransactionAnnotationProcessor - implements BeanPostProcessor, Ordered, ApplicationContextAware { - private final static Logger log = LoggerFactory.getLogger(RocketMQTransactionAnnotationProcessor.class); - - private ApplicationContext applicationContext; - private final Set> nonProcessedClasses = - Collections.newSetFromMap(new ConcurrentHashMap, Boolean>(64)); - - private RocketMQTemplate rocketMQTemplate; - - public RocketMQTransactionAnnotationProcessor(RocketMQTemplate rocketMQTemplate) { - this.rocketMQTemplate = rocketMQTemplate; - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - @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 (rocketMQTemplate == 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); - } - - ((TransactionMQProducer) rocketMQTemplate.getProducer()).setExecutorService(new ThreadPoolExecutor(listener.corePoolSize(), listener.maximumPoolSize(), - listener.keepAliveTime(), TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(listener.blockingQueueSize()))); - ((TransactionMQProducer) rocketMQTemplate.getProducer()).setTransactionListener(RocketMQUtil.convert((RocketMQLocalTransactionListener) bean)); - - } - - @Override - public int getOrder() { - return LOWEST_PRECEDENCE; - } - -} 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 1072b764..c655696e 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 @@ -26,6 +26,7 @@ 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.support.RocketMQUtil; @@ -519,6 +520,9 @@ public void destroy() { public TransactionSendResult sendMessageInTransaction(final String destination, final Message message, final Object arg) throws MessagingException { try { + if (((TransactionMQProducer) producer).getTransactionListener() == null) { + throw new IllegalStateException("The rocketMQTemplate does not exist TransactionListener"); + } org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); return producer.sendMessageInTransaction(rocketMsg, arg); } catch (MQClientException e) { diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/ExtRocketMQTemplateTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/ExtRocketMQTemplateTest.java new file mode 100644 index 00000000..7430ff54 --- /dev/null +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/ExtRocketMQTemplateTest.java @@ -0,0 +1,99 @@ +/* + * 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 javax.annotation.Resource; +import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; +import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; +import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessagingException; +import org.springframework.messaging.support.MessageBuilder; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) + +@SpringBootTest(properties = { + "rocketmq.nameServer=127.0.0.1:9876", "rocketmq.producer.group=extRocketMQTemplate-test-producer_group"}, classes = {RocketMQAutoConfiguration.class, ExtRocketMQTemplate.class, ExtTransactionListenerImpl.class}) +public class ExtRocketMQTemplateTest { + + @Resource(name = "extRocketMQTemplate") + private RocketMQTemplate extRocketMQTemplate; + + @Resource + private RocketMQTemplate rocketMQTemplate; + + @Test + public void testProperties() { + assertThat(extRocketMQTemplate.getProducer().getNamesrvAddr()).isEqualTo("172.0.0.1:9876"); + assertThat(extRocketMQTemplate.getProducer().getProducerGroup()).isEqualTo("extRocketMQTemplate-test-group"); + assertThat(extRocketMQTemplate.getProducer().getSendMsgTimeout()).isEqualTo(3000); + assertThat(extRocketMQTemplate.getProducer().getMaxMessageSize()).isEqualTo(4 * 1024); + } + + @Test + public void testTransactionListener() { + assertThat(((TransactionMQProducer) extRocketMQTemplate.getProducer()).getTransactionListener()).isNotNull(); + assertThat(((TransactionMQProducer) rocketMQTemplate.getProducer()).getTransactionListener()).isNull(); + } + + @Test + public void testSendTransactionalMessage() { + try { + rocketMQTemplate.sendMessageInTransaction("test-topic", MessageBuilder.withPayload("payload").build(), null); + } catch (IllegalStateException e) { + assertThat(e).hasMessageContaining("The rocketMQTemplate does not exist TransactionListener"); + } + + try { + extRocketMQTemplate.sendMessageInTransaction("test-topic", MessageBuilder.withPayload("payload").build(), null); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.client.exception.MQClientException: send message Exception"); + } + + } +} + +@ExtRocketMQTemplateConfiguration(nameServer = "172.0.0.1:9876", group = "extRocketMQTemplate-test-group", + sendMessageTimeout = 3000, maxMessageSize = 4 * 1024) +class ExtRocketMQTemplate extends RocketMQTemplate { + +} + +@RocketMQTransactionListener(rocketMQTemplateBeanName = "extRocketMQTemplate") +class ExtTransactionListenerImpl implements RocketMQLocalTransactionListener { + @Override + public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { + return RocketMQLocalTransactionState.UNKNOWN; + } + + @Override + public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { + return RocketMQLocalTransactionState.COMMIT; + } +} + + + + + diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java index 0b88a751..a6cc91db 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java @@ -17,34 +17,47 @@ package org.apache.rocketmq.spring.core; import javax.annotation.Resource; +import org.apache.rocketmq.client.AccessChannel; 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.spring.annotation.RocketMQTransactionListener; import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.messaging.Message; import org.springframework.messaging.MessagingException; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest(properties = {"rocketmq.nameServer=127.0.0.1:9876", "rocketmq.producer.group=producer_group"}, classes = RocketMQAutoConfiguration.class) +@SpringBootTest(properties = { + "rocketmq.nameServer=127.0.0.1:9876", "rocketmq.producer.group=rocketMQTemplate-test-producer_group", + "test.rocketmq.topic=test", "rocketmq.producer.access-key=test-ak", + "rocketmq.producer.secret-key=test-sk", "rocketmq.accessChannel=LOCAL", + "rocketmq.producer.sendMessageTimeout= 3500", "rocketmq.producer.retryTimesWhenSendFailed=3", + "rocketmq.producer.retryTimesWhenSendAsyncFailed=3"}, classes = {RocketMQAutoConfiguration.class, TransactionListenerImpl.class}) public class RocketMQTemplateTest { @Resource RocketMQTemplate rocketMQTemplate; + @Value("${test.rocketmq.topic}") + String topic; + @Test public void testSendMessage() { try { - rocketMQTemplate.syncSend("test", "payload"); + rocketMQTemplate.syncSend(topic, "payload"); } catch (MessagingException e) { assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); } try { - rocketMQTemplate.asyncSend("test", "payload", new SendCallback() { + rocketMQTemplate.asyncSend(topic, "payload", new SendCallback() { @Override public void onSuccess(SendResult sendResult) { } @@ -58,9 +71,39 @@ public void testSendMessage() { } try { - rocketMQTemplate.syncSendOrderly("test", "payload", "hashkey"); + rocketMQTemplate.syncSendOrderly(topic, "payload", "hashkey"); } catch (MessagingException e) { assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); } } + + @Test + public void testProperties() { + assertThat(rocketMQTemplate.getProducer().getNamesrvAddr()).isEqualTo("127.0.0.1:9876"); + assertThat(rocketMQTemplate.getProducer().getProducerGroup()).isEqualTo("rocketMQTemplate-test-producer_group"); + assertThat(rocketMQTemplate.getProducer().getAccessChannel()).isEqualTo(AccessChannel.LOCAL); + assertThat(rocketMQTemplate.getProducer().getSendMsgTimeout()).isEqualTo(3500); + assertThat(rocketMQTemplate.getProducer().getMaxMessageSize()).isEqualTo(4 * 1024 * 1024); + assertThat(rocketMQTemplate.getProducer().getRetryTimesWhenSendAsyncFailed()).isEqualTo(3); + assertThat(rocketMQTemplate.getProducer().getRetryTimesWhenSendFailed()).isEqualTo(3); + assertThat(rocketMQTemplate.getProducer().getCompressMsgBodyOverHowmuch()).isEqualTo(1024 * 4); + } + + @Test + public void testTransactionListener() { + assertThat(((TransactionMQProducer) rocketMQTemplate.getProducer()).getTransactionListener()).isNotNull(); + } +} + +@RocketMQTransactionListener +class TransactionListenerImpl implements RocketMQLocalTransactionListener { + @Override + public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { + return RocketMQLocalTransactionState.UNKNOWN; + } + + @Override + public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { + return RocketMQLocalTransactionState.COMMIT; + } } From ec1b41c3b07c4f3b68e1369e4bfc0406d91af50c Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 13 Dec 2019 16:31:39 +0800 Subject: [PATCH 049/105] chore(sample):add extRocketMQTemplate send transactional messages sample --- .../springboot/ProducerApplication.java | 66 ++++++++++++++----- 1 file changed, 50 insertions(+), 16 deletions(-) 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 4771bea3..d914bb57 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 @@ -17,6 +17,12 @@ package org.apache.rocketmq.samples.springboot; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Resource; import org.apache.rocketmq.client.producer.SendCallback; import org.apache.rocketmq.client.producer.SendResult; import org.apache.rocketmq.samples.springboot.domain.OrderPaidEvent; @@ -36,13 +42,6 @@ import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.MimeTypeUtils; -import javax.annotation.Resource; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; - /** * Producer, using RocketMQTemplate sends a variety of messages */ @@ -74,11 +73,11 @@ public void run(String... args) throws Exception { SendResult sendResult = rocketMQTemplate.syncSend(springTopic, "Hello, World!"); System.out.printf("syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); - sendResult = rocketMQTemplate.syncSend(userTopic, new User().setUserAge((byte)18).setUserName("Kitty")); + sendResult = rocketMQTemplate.syncSend(userTopic, new User().setUserAge((byte) 18).setUserName("Kitty")); System.out.printf("syncSend1 to topic %s sendResult=%s %n", userTopic, sendResult); sendResult = rocketMQTemplate.syncSend(userTopic, MessageBuilder.withPayload( - new User().setUserAge((byte)21).setUserName("Lester")).setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE).build()); + new User().setUserAge((byte) 21).setUserName("Lester")).setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON_VALUE).build()); System.out.printf("syncSend1 to topic %s sendResult=%s %n", userTopic, sendResult); // Use the extRocketMQTemplate @@ -112,8 +111,11 @@ public void onException(Throwable var1) { // Send a batch of strings testBatchMessages(); - // Send transactional messages - testTransaction(); + // Send transactional messages using rocketMQTemplate + testRocketMQTemplateTransaction(); + + // Send transactional messages using extRocketMQTemplate + testExtRocketMQTemplateTransaction(); } private void testBatchMessages() { @@ -128,16 +130,33 @@ private void testBatchMessages() { System.out.printf("--- Batch messages send result :" + sr); } - private void testTransaction() throws MessagingException { + private void testRocketMQTemplateTransaction() 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). + Message msg = MessageBuilder.withPayload("rocketMQTemplate transactional message " + i). setHeader(RocketMQHeaders.TRANSACTION_ID, "KEY_" + i).build(); SendResult sendResult = rocketMQTemplate.sendMessageInTransaction( springTransTopic + ":" + tags[i % tags.length], msg, null); - System.out.printf("------ send Transactional msg body = %s , sendResult=%s %n", + System.out.printf("------rocketMQTemplate send Transactional msg body = %s , sendResult=%s %n", + msg.getPayload(), sendResult.getSendStatus()); + + Thread.sleep(10); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void testExtRocketMQTemplateTransaction() throws MessagingException { + for (int i = 0; i < 10; i++) { + try { + Message msg = MessageBuilder.withPayload("extRocketMQTemplate transactional message " + i). + setHeader(RocketMQHeaders.TRANSACTION_ID, "KEY_" + i).build(); + SendResult sendResult = extRocketMQTemplate.sendMessageInTransaction( + springTransTopic, msg, null); + System.out.printf("------ExtRocketMQTemplate send Transactional msg body = %s , sendResult=%s %n", msg.getPayload(), sendResult.getSendStatus()); Thread.sleep(10); @@ -155,7 +174,7 @@ class TransactionListenerImpl implements RocketMQLocalTransactionListener { @Override public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { - String transId = (String)msg.getHeaders().get(RocketMQHeaders.TRANSACTION_ID); + String transId = (String) msg.getHeaders().get(RocketMQHeaders.TRANSACTION_ID); System.out.printf("#### executeLocalTransaction is executed, msgTransactionId=%s %n", transId); int value = transactionIndex.getAndIncrement(); @@ -181,7 +200,7 @@ public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object @Override public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { - String transId = (String)msg.getHeaders().get(RocketMQHeaders.TRANSACTION_ID); + String transId = (String) msg.getHeaders().get(RocketMQHeaders.TRANSACTION_ID); RocketMQLocalTransactionState retState = RocketMQLocalTransactionState.COMMIT; Integer status = localTrans.get(transId); if (null != status) { @@ -204,4 +223,19 @@ public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { } } + @RocketMQTransactionListener(rocketMQTemplateBeanName = "extRocketMQTemplate") + class ExtTransactionListenerImpl implements RocketMQLocalTransactionListener { + @Override + public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { + System.out.printf("ExtTransactionListenerImpl executeLocalTransaction and return UNKNOWN. \n"); + return RocketMQLocalTransactionState.UNKNOWN; + } + + @Override + public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { + System.out.printf("ExtTransactionListenerImpl checkLocalTransaction and return COMMIT. \n"); + return RocketMQLocalTransactionState.COMMIT; + } + } + } From 054d3e51ab45b89951453d2e0dcfea74b74ed5f8 Mon Sep 17 00:00:00 2001 From: zhangjidi Date: Thu, 19 Dec 2019 17:39:31 +0800 Subject: [PATCH 050/105] [ISSUE #151] Fix the Infinite loop in DefaultRocketMQListenerContainer --- .../DefaultRocketMQListenerContainer.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) 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 ad59bc99..691e5163 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 @@ -425,33 +425,33 @@ private MethodParameter getMethodParameter() { private Type getMessageType() { Class targetClass = AopProxyUtils.ultimateTargetClass(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) { - ParameterizedType parameterizedType = (ParameterizedType) type; - if (Objects.equals(parameterizedType.getRawType(), RocketMQListener.class)) { - Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); - if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) { - return actualTypeArguments[0]; - } else { - return Object.class; - } + Type matchedGenericInterface = null; + while (Objects.nonNull(targetClass)) { + Type[] interfaces = targetClass.getGenericInterfaces(); + if (Objects.nonNull(interfaces)) { + for (Type type : interfaces) { + if (type instanceof ParameterizedType + && Objects.equals(((ParameterizedType) type).getRawType(), RocketMQListener.class)) { + matchedGenericInterface = type; + break; } } } - - return Object.class; - } else { + targetClass = targetClass.getSuperclass(); + } + if (Objects.isNull(matchedGenericInterface)) { return Object.class; } + + Type[] actualTypeArguments = ((ParameterizedType) matchedGenericInterface).getActualTypeArguments(); + if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) { + return actualTypeArguments[0]; + } + return Object.class; } + + private void initRocketMQPushConsumer() throws MQClientException { Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); From ce94b6adf0d680903305df2533bfd739541f0f5c Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Tue, 24 Dec 2019 15:36:35 +0800 Subject: [PATCH 051/105] enhancement(extRocketMQTemplate):Remove the limitation that ExtRocketMQTemplate can not keep the same nameserver as RocketMQTemplate --- .../ExtRocketMQTemplateConfiguration.java | 5 ++--- .../ExtProducerResetConfiguration.java | 7 ------- .../RocketMQAutoConfigurationTest.java | 14 -------------- 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ExtRocketMQTemplateConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ExtRocketMQTemplateConfiguration.java index c268b571..05eaa466 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ExtRocketMQTemplateConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ExtRocketMQTemplateConfiguration.java @@ -17,13 +17,12 @@ package org.apache.rocketmq.spring.annotation; -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; +import org.springframework.stereotype.Component; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @@ -38,7 +37,7 @@ /** * The property of "name-server". */ - String nameServer(); + String nameServer() default "${rocketmq.name-server:}"; /** * Name of producer. diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index 1c019bbf..daab3c35 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -162,12 +162,5 @@ private void validate(ExtRocketMQTemplateConfiguration annotation, "please check the @ExtRocketMQTemplateConfiguration", annotation.value())); } - - if (rocketMQProperties.getNameServer() == null || - rocketMQProperties.getNameServer().equals(environment.resolvePlaceholders(annotation.nameServer()))) { - throw new BeanDefinitionValidationException( - "Bad annotation definition in @ExtRocketMQTemplateConfiguration, nameServer property is same with " + - "global property, please use the default RocketMQTemplate!"); - } } } \ No newline at end of file diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index 553183d1..5c0ccca7 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -32,11 +32,8 @@ import org.junit.Assert; import org.junit.Test; import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.support.BeanDefinitionValidationException; import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.Message; @@ -88,17 +85,6 @@ public void testDefaultMQProducer() { @Test public void testExtRocketMQTemplate() { - runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). - withUserConfiguration(TestExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). - run(new ContextConsumer() { - @Override - public void accept(AssertableApplicationContext context) throws Throwable { - Throwable th = context.getStartupFailure(); - System.out.printf("th==" + th + "\n"); - Assert.assertTrue(th instanceof BeanDefinitionValidationException); - } - }); - runner.withPropertyValues("rocketmq.name-server=127.0.1.1:9876"). withUserConfiguration(TestExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). run((context) -> { From 72753403b5526b04140101afd75a6a7987c30302 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Wed, 25 Dec 2019 16:33:53 +0800 Subject: [PATCH 052/105] chore(readme):add wiki link --- README.md | 4 +- README_zh_CN.md | 391 ------------------- rocketmq-spring-boot-samples/README.md | 2 - rocketmq-spring-boot-samples/README_zh_CN.md | 40 -- 4 files changed, 2 insertions(+), 435 deletions(-) delete mode 100644 README_zh_CN.md delete mode 100644 rocketmq-spring-boot-samples/README_zh_CN.md diff --git a/README.md b/README.md index 210147d0..2f59a7bd 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,9 @@ Add a dependency using maven: Please see the [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples) -## Document +## User Guide -Please see the [wiki]() page +Please see the [wiki](https://github.com/apache/rocketmq-spring/wiki) page ## Contributing diff --git a/README_zh_CN.md b/README_zh_CN.md deleted file mode 100644 index 3e263074..00000000 --- a/README_zh_CN.md +++ /dev/null @@ -1,391 +0,0 @@ -# RocketMQ-Spring [![Build Status](https://travis-ci.org/apache/rocketmq-spring.svg?branch=master)](https://travis-ci.org/apache/rocketmq-spring) - -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.rocketmq/rocketmq-spring-all/badge.svg)](https://search.maven.org/search?q=g:org.apache.rocketmq%20AND%20a:rocketmq-spring-all) -[![GitHub release](https://img.shields.io/badge/release-download-orange.svg)](https://github.com/apache/rocketmq-spring/releases) -[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) - -[English](./README.md) - -帮助开发者在[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] 并发消费(广播/集群) -- [x] one-way方式发送 -- [x] 事务方式发送 -- [x] 消息轨迹 -- [x] ACL -- [ ] pull消费 - -## Quick Start - -下面列出来了一些关键点,完整的示例请参考: [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples) - -注意:当前的RELEASE.VERSION=2.0.4 - -```xml - - - org.apache.rocketmq - rocketmq-spring-boot-starter - ${RELEASE.VERSION} - -``` - -### 发送消息 - -```properties -## application.properties -rocketmq.name-server=127.0.0.1:9876 -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 -> rocketmq.producer.send-message-timeout=300000 -> rocketmq.producer.compress-message-body-threshold=4096 -> rocketmq.producer.max-message-size=4194304 -> rocketmq.producer.retry-times-when-send-async-failed=0 -> rocketmq.producer.retry-next-server=true -> rocketmq.producer.retry-times-when-send-failed=2 -> ``` - - -### 接收消息 - -```properties -## application.properties -rocketmq.name-server=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{ - 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{ - public void onMessage(OrderPaidEvent orderPaidEvent) { - log.info("received orderPaidEvent: {}", orderPaidEvent); - } - } -} -``` - - -> 更多消费相关配置 -> -> see: [RocketMQMessageListener](rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQMessageListener.java) - -### 消息轨迹 - -Producer 端要想使用消息轨迹,需要多配置两个配置项: - -```properties -## application.properties -rocketmq.name-server=127.0.0.1:9876 -rocketmq.producer.group=my-group - -rocketmq.producer.enable-msg-trace=true -rocketmq.producer.customized-trace-topic=my-trace-topic -``` - -Consumer 端消息轨迹的功能需要在 `@RocketMQMessageListener` 中进行配置对应的属性: - -``` -@Service -@RocketMQMessageListener( - topic = "test-topic-1", - consumerGroup = "my-consumer_test-topic-1", - enableMsgTrace = true, - customizedTraceTopic = "my-trace-topic" -) -public class MyConsumer implements RocketMQListener { - ... -} -``` - -> 注意: -> -> 默认情况下 Producer 和 Consumer 的消息轨迹功能是开启的且 trace-topic 为 RMQ_SYS_TRACE_TOPIC -> Consumer 端的消息轨迹 trace-topic 可以在配置文件中配置 `rocketmq.consumer.customized-trace-topic` 配置项,不需要为在每个 `@RocketMQTransactionListener` 配置 - - -### ACL - -Producer 端要想使用 ACL 功能,需要多配置两个配置项: - -```properties -## application.properties -rocketmq.name-server=127.0.0.1:9876 -rocketmq.producer.group=my-group - -rocketmq.producer.access-key=AK -rocketmq.producer.secret-key=SK -``` - -事务消息的发送需要在 `@RocketMQTransactionListener` 注解里配置上 AK/SK: - -``` -@RocketMQTransactionListener( - txProducerGroup = "test, - accessKey = "AK", - secretKey = "SK" -) -class TransactionListenerImpl implements RocketMQLocalTransactionListener { - ... -} -``` - -> 注意: -> -> 可以不用为每个 `@RocketMQTransactionListener` 注解配置 AK/SK,在配置文件中配置 `rocketmq.producer.access-key` 和 `rocketmq.producer.secret-key` 配置项,这两个配置项的值就是默认值 - -Consumer 端 ACL 功能需要在 `@RocketMQMessageListener` 中进行配置 - -``` -@Service -@RocketMQMessageListener( - topic = "test-topic-1", - consumerGroup = "my-consumer_test-topic-1", - accessKey = "AK", - secretKey = "SK" -) -public class MyConsumer implements RocketMQListener { - ... -} -``` - -> 注意: -> -> 可以不用为每个 `@RocketMQMessageListener` 注解配置 AK/SK,在配置文件中配置 `rocketmq.consumer.access-key` 和 `rocketmq.consumer.secret-key` 配置项,这两个配置项的值就是默认值 - -## FAQ - -1. 生产环境有多个`nameserver`该如何连接? - - `rocketmq.name-server`支持配置多个`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{ - 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, 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进行关联,您也可以不指定这个值,从而使用默认的事务发送者组。 - -1. 如何声明不同name-server或者其他特定的属性来定义非标的RocketMQTemplate? - ```java - // 第一步: 定义非标的RocketMQTemplate使用你需要的属性,注意,这里的'nameServer'属性必须要定义,并且其取值不能与全局配置属性'rocketmq.name-server'相同 - // 也可以定义其他属性,如果不定义,它们取全局的配置属性值或默认值。 - - // 这个RocketMQTemplate的Spring Bean名是'extRocketMQTemplate', 与所定义的类名相同(但首字母小写) - @ExtRocketMQTemplateConfiguration(nameServer="127.0.0.1:9876" - , ... // 定义其他属性,如果有必要。 - ) - public class ExtRocketMQTemplate extends RocketMQTemplate { - //类里面不需要做任何修改 - } - - - // 第二步: 使用这个非标RocketMQTemplate - @Resource(name = "extRocketMQTemplate") // 这里必须定义name属性来指向上具体的Spring Bean. - private RocketMQTemplate extRocketMQTemplate; - // 接下来就可以正常使用这个extRocketMQTemplate了. - - ``` - -1. MessageListener消费端,是否可以指定不同的name-server而不是使用全局定义的'rocketmq.name-server'属性值 ? - - ```java - @Service - @RocketMQMessageListener( - nameServer = "NEW-NAMESERVER-LIST", // 可以使用这个optional属性来指定不同的name-server - topic = "test-topic-1", - consumerGroup = "my-consumer_test-topic-1", - enableMsgTrace = true, - customizedTraceTopic = "my-trace-topic" - ) - public class MyNameServerConsumer implements RocketMQListener { - ... - } - ``` \ No newline at end of file diff --git a/rocketmq-spring-boot-samples/README.md b/rocketmq-spring-boot-samples/README.md index d1f2b273..ae5c3836 100644 --- a/rocketmq-spring-boot-samples/README.md +++ b/rocketmq-spring-boot-samples/README.md @@ -1,7 +1,5 @@ # 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) diff --git a/rocketmq-spring-boot-samples/README_zh_CN.md b/rocketmq-spring-boot-samples/README_zh_CN.md deleted file mode 100644 index c8f27d1c..00000000 --- a/rocketmq-spring-boot-samples/README_zh_CN.md +++ /dev/null @@ -1,40 +0,0 @@ -# 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) - - -## 在本地运行这个测试例子 - -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 -``` -结合测试代码,观察窗口中消息的发送和接收情况 From 7fcff55bf7a95f1f715b65912878e1ebbfaf60cc Mon Sep 17 00:00:00 2001 From: von gosling Date: Wed, 25 Dec 2019 17:39:11 +0800 Subject: [PATCH 053/105] docs(readme): some syntax optimization --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 2f59a7bd..8ee37284 100644 --- a/README.md +++ b/README.md @@ -11,16 +11,16 @@ This project aims to help developers quickly integrate [RocketMQ](http://rocketm - [x] Send messages synchronously - [x] Send messages asynchronously - [x] Send messages in one-way mode -- [x] Send messages orderly -- [x] Send messages in batch +- [x] Send ordered messages +- [x] Send batched messages - [x] Send transactional messages - [x] Send scheduled messages with delay level - [x] Consume messages with concurrently mode (broadcasting/clustering) -- [x] Consume messages with orderly mode -- [x] Support message filter with tag and sql -- [x] Support message tracing capability -- [x] Authentication and authorisation -- [ ] Request-reply mode +- [x] Consume ordered messages +- [x] Filter messages using the tag or sql92 expression +- [x] Suport message tracing +- [x] Support Authentication and authorisation +- [ ] Support Request-reply message exchange pattern ## Prerequisites - JDK 1.8 and above @@ -42,16 +42,16 @@ Add a dependency using maven: ## Samples -Please see the [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples) +Please see the [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples). ## User Guide -Please see the [wiki](https://github.com/apache/rocketmq-spring/wiki) page +Please see the [wiki](https://github.com/apache/rocketmq-spring/wiki) page. ## Contributing -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/) +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/). ## License -[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) Copyright (C) Apache Software Foundation \ No newline at end of file +[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) Copyright (C) Apache Software Foundation From bf8e248477bacacdc81b7de94276546a38f47aa3 Mon Sep 17 00:00:00 2001 From: von gosling Date: Wed, 25 Dec 2019 17:41:43 +0800 Subject: [PATCH 054/105] docs(readme): lower-case letter --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8ee37284..833a5927 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ This project aims to help developers quickly integrate [RocketMQ](http://rocketm - [x] Consume ordered messages - [x] Filter messages using the tag or sql92 expression - [x] Suport message tracing -- [x] Support Authentication and authorisation -- [ ] Support Request-reply message exchange pattern +- [x] Support authentication and authorisation +- [ ] Support request-reply message exchange pattern ## Prerequisites - JDK 1.8 and above From 1aea7e1b8486c523317070953903a515acad1a20 Mon Sep 17 00:00:00 2001 From: von gosling Date: Thu, 26 Dec 2019 11:56:56 +0800 Subject: [PATCH 055/105] docs(readme): fix the typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 833a5927..a5d9429e 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ This project aims to help developers quickly integrate [RocketMQ](http://rocketm - [x] Consume ordered messages - [x] Filter messages using the tag or sql92 expression - [x] Suport message tracing -- [x] Support authentication and authorisation +- [x] Support authentication and authorization - [ ] Support request-reply message exchange pattern ## Prerequisites From c35472654c9ca9ddf98b2299810833b7318c6c6b Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 27 Dec 2019 11:31:13 +0800 Subject: [PATCH 056/105] chore(all):polish the code and modify the version --- pom.xml | 2 +- rocketmq-spring-boot-parent/pom.xml | 4 +- rocketmq-spring-boot-samples/pom.xml | 2 +- rocketmq-spring-boot-starter/pom.xml | 4 +- rocketmq-spring-boot/pom.xml | 4 +- .../ExtProducerResetConfiguration.java | 34 +----- .../RocketMQAutoConfiguration.java | 31 +----- .../autoconfigure/RocketMQProperties.java | 2 +- .../DefaultRocketMQListenerContainer.java | 105 +++++++++--------- .../rocketmq/spring/support/RocketMQUtil.java | 61 +++++++--- 10 files changed, 113 insertions(+), 136 deletions(-) diff --git a/pom.xml b/pom.xml index f8acf1d0..827ae1a7 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.0.5-SNAPSHOT + 2.1.0-SNAPSHOT pom Apache RocketMQ Spring Boot ${project.version} diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index ca490b01..bf62ce49 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.0.5-SNAPSHOT + 2.1.0-SNAPSHOT ../pom.xml @@ -38,7 +38,7 @@ 2.0.5.RELEASE 5.1.0.RELEASE - 2.0.5-SNAPSHOT + 2.1.0-SNAPSHOT 4.6.0 1.7.25 diff --git a/rocketmq-spring-boot-samples/pom.xml b/rocketmq-spring-boot-samples/pom.xml index 983a2d49..1787afdd 100644 --- a/rocketmq-spring-boot-samples/pom.xml +++ b/rocketmq-spring-boot-samples/pom.xml @@ -38,7 +38,7 @@ - 2.0.5-SNAPSHOT + 2.1.0-SNAPSHOT diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml index 697ab169..71ea5cda 100644 --- a/rocketmq-spring-boot-starter/pom.xml +++ b/rocketmq-spring-boot-starter/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.0.5-SNAPSHOT + 2.1.0-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml @@ -30,7 +30,7 @@ jar RocketMQ Spring Boot Starter - SRocketMQ Spring Boot Starter + RocketMQ Spring Boot Starter https://github.com/apache/rocketmq-spring diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml index d5d5505f..cd1d2a40 100644 --- a/rocketmq-spring-boot/pom.xml +++ b/rocketmq-spring-boot/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.0.5-SNAPSHOT + 2.1.0-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml @@ -30,7 +30,7 @@ jar RocketMQ Spring Boot AutoConfigure - SRocketMQ Spring Boot AutoConfigure + RocketMQ Spring Boot AutoConfigure https://github.com/apache/rocketmq-spring diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index 1c019bbf..b62d20ae 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -17,19 +17,14 @@ package org.apache.rocketmq.spring.autoconfigure; -import java.lang.reflect.Field; import java.util.Map; import java.util.Objects; -import org.apache.rocketmq.acl.common.AclClientRPCHook; -import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; -import org.apache.rocketmq.client.producer.TransactionMQProducer; -import org.apache.rocketmq.client.trace.AsyncTraceDispatcher; -import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl; import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; +import org.apache.rocketmq.spring.support.RocketMQUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; @@ -104,7 +99,6 @@ private void registerTemplate(String beanName, Object bean) { } private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annotation) { - DefaultMQProducer producer = null; RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer(); if (producerConfig == null) { @@ -118,35 +112,15 @@ private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annota ak = StringUtils.isEmpty(ak) ? producerConfig.getAccessKey() : annotation.accessKey(); String sk = environment.resolvePlaceholders(annotation.secretKey()); sk = StringUtils.isEmpty(sk) ? producerConfig.getSecretKey() : annotation.secretKey(); + boolean isEnableMsgTrace = annotation.enableMsgTrace(); String customizedTraceTopic = environment.resolvePlaceholders(annotation.customizedTraceTopic()); customizedTraceTopic = StringUtils.isEmpty(customizedTraceTopic) ? producerConfig.getCustomizedTraceTopic() : customizedTraceTopic; - boolean isEnableAcl = !StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk); - - if (isEnableAcl) { - producer = new TransactionMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk))); - producer.setVipChannelEnabled(false); - } else { - producer = new TransactionMQProducer(groupName); - } - - if (annotation.enableMsgTrace()) { - try { - AsyncTraceDispatcher dispatcher = new AsyncTraceDispatcher(customizedTraceTopic, isEnableAcl ? new AclClientRPCHook(new SessionCredentials(ak, sk)) : null); - dispatcher.setHostProducer(producer.getDefaultMQProducerImpl()); - Field field = DefaultMQProducer.class.getDeclaredField("traceDispatcher"); - field.setAccessible(true); - field.set(producer, dispatcher); - producer.getDefaultMQProducerImpl().registerSendMessageHook( - new SendMessageTraceHookImpl(dispatcher)); - } catch (Throwable e) { - log.error("system mqtrace hook init failed ,maybe can't send msg trace data"); - } - } + DefaultMQProducer producer = RocketMQUtil.createDefaultMQProducer(groupName, ak, sk, isEnableMsgTrace, customizedTraceTopic); producer.setNamesrvAddr(nameServer); producer.setSendMsgTimeout(annotation.sendMessageTimeout() == -1 ? producerConfig.getSendMessageTimeout() : annotation.sendMessageTimeout()); - producer.setRetryTimesWhenSendFailed(annotation.retryTimesWhenSendAsyncFailed() == -1 ? producerConfig.getRetryTimesWhenSendFailed() : annotation.retryTimesWhenSendAsyncFailed()); + producer.setRetryTimesWhenSendFailed(annotation.retryTimesWhenSendFailed() == -1 ? producerConfig.getRetryTimesWhenSendFailed() : annotation.retryTimesWhenSendAsyncFailed()); producer.setRetryTimesWhenSendAsyncFailed(annotation.retryTimesWhenSendAsyncFailed() == -1 ? producerConfig.getRetryTimesWhenSendAsyncFailed() : annotation.retryTimesWhenSendAsyncFailed()); producer.setMaxMessageSize(annotation.maxMessageSize() == -1 ? producerConfig.getMaxMessageSize() : annotation.maxMessageSize()); producer.setCompressMsgBodyOverHowmuch(annotation.compressMessageBodyThreshold() == -1 ? producerConfig.getCompressMessageBodyThreshold() : annotation.compressMessageBodyThreshold()); diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java index 14f7160c..e6131e78 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java @@ -17,18 +17,13 @@ package org.apache.rocketmq.spring.autoconfigure; -import java.lang.reflect.Field; import javax.annotation.PostConstruct; -import org.apache.rocketmq.acl.common.AclClientRPCHook; -import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.client.MQAdmin; import org.apache.rocketmq.client.producer.DefaultMQProducer; -import org.apache.rocketmq.client.producer.TransactionMQProducer; -import org.apache.rocketmq.client.trace.AsyncTraceDispatcher; -import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; +import org.apache.rocketmq.spring.support.RocketMQUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -84,30 +79,12 @@ public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties String accessChannel = rocketMQProperties.getAccessChannel(); - DefaultMQProducer producer; String ak = rocketMQProperties.getProducer().getAccessKey(); String sk = rocketMQProperties.getProducer().getSecretKey(); - boolean isEnableAcl = !StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk); - if (isEnableAcl) { - producer = new TransactionMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk))); - producer.setVipChannelEnabled(false); - } else { - producer = new TransactionMQProducer(groupName); - } + boolean isEnableMsgTrace = rocketMQProperties.getProducer().isEnableMsgTrace(); + String customizedTraceTopic = rocketMQProperties.getProducer().getCustomizedTraceTopic(); - if (rocketMQProperties.getProducer().isEnableMsgTrace()) { - try { - AsyncTraceDispatcher dispatcher = new AsyncTraceDispatcher(rocketMQProperties.getProducer().getCustomizedTraceTopic(), isEnableAcl ? new AclClientRPCHook(new SessionCredentials(ak, sk)) : null); - dispatcher.setHostProducer(producer.getDefaultMQProducerImpl()); - Field field = DefaultMQProducer.class.getDeclaredField("traceDispatcher"); - field.setAccessible(true); - field.set(producer, dispatcher); - producer.getDefaultMQProducerImpl().registerSendMessageHook( - new SendMessageTraceHookImpl(dispatcher)); - } catch (Throwable e) { - log.error("system mqtrace hook init failed ,maybe can't send msg trace data"); - } - } + DefaultMQProducer producer = RocketMQUtil.createDefaultMQProducer(groupName, ak, sk, isEnableMsgTrace, customizedTraceTopic); producer.setNamesrvAddr(nameServer); if (!StringUtils.isEmpty(accessChannel)) { diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java index 832d0219..19573898 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java @@ -33,7 +33,7 @@ public class RocketMQProperties { private String nameServer; /** - * Enum type for accesChannel, values: LOCAL, CLOUD + * Enum type for accessChannel, values: LOCAL, CLOUD */ private String accessChannel; 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 ad59bc99..ecf23541 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 @@ -209,14 +209,14 @@ public SelectorType getSelectorType() { return selectorType; } - public void setSelectorExpression(String selectorExpression) { - this.selectorExpression = selectorExpression; - } - public String getSelectorExpression() { return selectorExpression; } + public void setSelectorExpression(String selectorExpression) { + this.selectorExpression = selectorExpression; + } + public MessageModel getMessageModel() { return messageModel; } @@ -296,7 +296,6 @@ public int getPhase() { return Integer.MAX_VALUE; } - @Override public void afterPropertiesSet() throws Exception { initRocketMQPushConsumer(); @@ -328,53 +327,6 @@ public void setName(String name) { this.name = name; } - public class DefaultMessageListenerConcurrently implements MessageListenerConcurrently { - - @SuppressWarnings("unchecked") - @Override - public ConsumeConcurrentlyStatus consumeMessage(List 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") - @Override - public ConsumeOrderlyStatus consumeMessage(List 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)) { @@ -402,7 +354,6 @@ private Object doConvertMessage(MessageExt messageExt) { } } - private MethodParameter getMethodParameter() { Class targetClass = AopProxyUtils.ultimateTargetClass(rocketMQListener); Type messageType = this.getMessageType(); @@ -470,7 +421,7 @@ private void initRocketMQPushConsumer() throws MQClientException { } else { log.debug("Access-key or secret-key not configure in " + this + "."); consumer = new DefaultMQPushConsumer(consumerGroup, enableMsgTrace, - this.applicationContext.getEnvironment(). + this.applicationContext.getEnvironment(). resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); } @@ -528,4 +479,50 @@ private void initRocketMQPushConsumer() throws MQClientException { } + public class DefaultMessageListenerConcurrently implements MessageListenerConcurrently { + + @SuppressWarnings("unchecked") + @Override + public ConsumeConcurrentlyStatus consumeMessage(List 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") + @Override + public ConsumeOrderlyStatus consumeMessage(List 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; + } + } + } 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 index 4c731f24..5352b190 100644 --- 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 @@ -17,11 +17,19 @@ package org.apache.rocketmq.spring.support; import com.fasterxml.jackson.databind.ObjectMapper; +import java.lang.reflect.Field; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.Objects; import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.LocalTransactionState; import org.apache.rocketmq.client.producer.TransactionListener; +import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.client.trace.AsyncTraceDispatcher; +import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl; import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.common.message.Message; import org.apache.rocketmq.common.message.MessageConst; @@ -39,10 +47,6 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; -import java.nio.charset.Charset; -import java.util.Map; -import java.util.Objects; - public class RocketMQUtil { private final static Logger log = LoggerFactory.getLogger(RocketMQUtil.class); @@ -73,7 +77,7 @@ private static LocalTransactionState convertLocalTransactionState(RocketMQLocalT } // Never happen - log.warn("Failed to covert enum type RocketMQLocalTransactionState.%s", state); + log.warn("Failed to covert enum type RocketMQLocalTransactionState {}.", state); return LocalTransactionState.UNKNOW; } @@ -136,9 +140,9 @@ public static org.apache.rocketmq.common.message.Message convertToRocketMessage( byte[] payloads; if (payloadObj instanceof String) { - payloads = ((String)payloadObj).getBytes(Charset.forName(charset)); + payloads = ((String) payloadObj).getBytes(Charset.forName(charset)); } else if (payloadObj instanceof byte[]) { - payloads = (byte[])message.getPayload(); + payloads = (byte[]) message.getPayload(); } else { try { String jsonObj = objectMapper.writeValueAsString(payloadObj); @@ -150,11 +154,6 @@ public static org.apache.rocketmq.common.message.Message convertToRocketMessage( return getAndWrapMessage(destination, message.getHeaders(), payloads); } - public static org.apache.rocketmq.common.message.Message convertToRocketMessage( - String destination, org.springframework.messaging.Message message) { - return getAndWrapMessage(destination, message.getHeaders(), message.getPayload()); - } - private static Message getAndWrapMessage(String destination, MessageHeaders headers, byte[] payloads) { if (destination == null || destination.length() < 1) { return null; @@ -210,11 +209,11 @@ public static org.apache.rocketmq.common.message.Message convertToRocketMessage( throw new RuntimeException("the message cannot be empty"); } if (payloadObj instanceof String) { - payloads = ((String)payloadObj).getBytes(Charset.forName(charset)); + payloads = ((String) payloadObj).getBytes(Charset.forName(charset)); } else if (payloadObj instanceof byte[]) { - payloads = (byte[])message.getPayload(); + payloads = (byte[]) message.getPayload(); } else { - String jsonObj = (String)messageConverter.fromMessage(message, payloadObj.getClass()); + String jsonObj = (String) messageConverter.fromMessage(message, payloadObj.getClass()); if (null == jsonObj) { throw new RuntimeException(String.format( "empty after conversion [messageConverter:%s,payloadClass:%s,payloadObj:%s]", @@ -247,11 +246,41 @@ public static RPCHook getRPCHookByAkSk(Environment env, String accessKeyOrExpr, public static String getInstanceName(RPCHook rpcHook, String identify) { String separator = "|"; StringBuilder instanceName = new StringBuilder(); - SessionCredentials sessionCredentials = ((AclClientRPCHook)rpcHook).getSessionCredentials(); + SessionCredentials sessionCredentials = ((AclClientRPCHook) rpcHook).getSessionCredentials(); instanceName.append(sessionCredentials.getAccessKey()) .append(separator).append(sessionCredentials.getSecretKey()) .append(separator).append(identify) .append(separator).append(UtilAll.getPid()); return instanceName.toString(); } + + public static DefaultMQProducer createDefaultMQProducer(String groupName, String ak, String sk, + boolean isEnableMsgTrace, String customizedTraceTopic) { + + boolean isEnableAcl = !StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk); + DefaultMQProducer producer; + if (isEnableAcl) { + producer = new TransactionMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk))); + producer.setVipChannelEnabled(false); + } else { + producer = new TransactionMQProducer(groupName); + } + + if (isEnableMsgTrace) { + try { + AsyncTraceDispatcher dispatcher = new AsyncTraceDispatcher(customizedTraceTopic, isEnableAcl ? new AclClientRPCHook(new SessionCredentials(ak, sk)) : null); + dispatcher.setHostProducer(producer.getDefaultMQProducerImpl()); + Field field = DefaultMQProducer.class.getDeclaredField("traceDispatcher"); + field.setAccessible(true); + field.set(producer, dispatcher); + producer.getDefaultMQProducerImpl().registerSendMessageHook( + new SendMessageTraceHookImpl(dispatcher)); + } catch (Throwable e) { + log.error("system trace hook init failed ,maybe can't send msg trace data"); + } + } + + return producer; + } + } From ecbe6f15d80c59372d3de162a4cf0b04a52f7dc3 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 27 Dec 2019 11:37:53 +0800 Subject: [PATCH 057/105] chore(all):wrong use annotation.retryTimesWhenSendAsyncFailed --- .../spring/autoconfigure/ExtProducerResetConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index b62d20ae..718e0fce 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -121,7 +121,7 @@ private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annota producer.setNamesrvAddr(nameServer); producer.setSendMsgTimeout(annotation.sendMessageTimeout() == -1 ? producerConfig.getSendMessageTimeout() : annotation.sendMessageTimeout()); producer.setRetryTimesWhenSendFailed(annotation.retryTimesWhenSendFailed() == -1 ? producerConfig.getRetryTimesWhenSendFailed() : annotation.retryTimesWhenSendAsyncFailed()); - producer.setRetryTimesWhenSendAsyncFailed(annotation.retryTimesWhenSendAsyncFailed() == -1 ? producerConfig.getRetryTimesWhenSendAsyncFailed() : annotation.retryTimesWhenSendAsyncFailed()); + producer.setRetryTimesWhenSendAsyncFailed(annotation.retryTimesWhenSendAsyncFailed() == -1 ? producerConfig.getRetryTimesWhenSendAsyncFailed() : annotation.retryTimesWhenSendFailed()); producer.setMaxMessageSize(annotation.maxMessageSize() == -1 ? producerConfig.getMaxMessageSize() : annotation.maxMessageSize()); producer.setCompressMsgBodyOverHowmuch(annotation.compressMessageBodyThreshold() == -1 ? producerConfig.getCompressMessageBodyThreshold() : annotation.compressMessageBodyThreshold()); producer.setRetryAnotherBrokerWhenNotStoreOK(annotation.retryNextServer()); From 29a8be07413915e1d95dcc9050413281b4366012 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 27 Dec 2019 11:41:54 +0800 Subject: [PATCH 058/105] chore(all):fix bad change --- .../spring/autoconfigure/ExtProducerResetConfiguration.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index 718e0fce..f0820720 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -120,8 +120,8 @@ private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annota producer.setNamesrvAddr(nameServer); producer.setSendMsgTimeout(annotation.sendMessageTimeout() == -1 ? producerConfig.getSendMessageTimeout() : annotation.sendMessageTimeout()); - producer.setRetryTimesWhenSendFailed(annotation.retryTimesWhenSendFailed() == -1 ? producerConfig.getRetryTimesWhenSendFailed() : annotation.retryTimesWhenSendAsyncFailed()); - producer.setRetryTimesWhenSendAsyncFailed(annotation.retryTimesWhenSendAsyncFailed() == -1 ? producerConfig.getRetryTimesWhenSendAsyncFailed() : annotation.retryTimesWhenSendFailed()); + producer.setRetryTimesWhenSendFailed(annotation.retryTimesWhenSendFailed() == -1 ? producerConfig.getRetryTimesWhenSendFailed() : annotation.retryTimesWhenSendFailed()); + producer.setRetryTimesWhenSendAsyncFailed(annotation.retryTimesWhenSendAsyncFailed() == -1 ? producerConfig.getRetryTimesWhenSendAsyncFailed() : annotation.retryTimesWhenSendAsyncFailed()); producer.setMaxMessageSize(annotation.maxMessageSize() == -1 ? producerConfig.getMaxMessageSize() : annotation.maxMessageSize()); producer.setCompressMsgBodyOverHowmuch(annotation.compressMessageBodyThreshold() == -1 ? producerConfig.getCompressMessageBodyThreshold() : annotation.compressMessageBodyThreshold()); producer.setRetryAnotherBrokerWhenNotStoreOK(annotation.retryNextServer()); From fb04c04afe3af681ee7bf26d30f7c76c860b7cab Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Wed, 8 Jan 2020 10:54:31 +0800 Subject: [PATCH 059/105] doc(readme):add new badge for readme doc --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a5d9429e..dfb8d0b8 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.rocketmq/rocketmq-spring-all/badge.svg)](https://search.maven.org/search?q=g:org.apache.rocketmq%20AND%20a:rocketmq-spring-all) [![GitHub release](https://img.shields.io/badge/release-download-orange.svg)](https://github.com/apache/rocketmq-spring/releases) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) +[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/apache/rocketmq-spring.svg)](http://isitmaintained.com/project/apache/rocketmq-spring "Average time to resolve an issue") +[![Percentage of issues still open](http://isitmaintained.com/badge/open/apache/rocketmq-spring.svg)](http://isitmaintained.com/project/apache/rocketmq-spring "Percentage of issues still open") This project aims to help developers quickly integrate [RocketMQ](http://rocketmq.apache.org/) with [Spring Boot](http://projects.spring.io/spring-boot/). From 64f149bbd76c3eda92905bd0ce3dfe5b2a7b6550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=90=91=E5=BE=80?= Date: Wed, 15 Jan 2020 20:46:57 +0800 Subject: [PATCH 060/105] [ISSUE #208]support request/reply model in rocketmq-spring (#209) * support request/response model in rocketmq-spring * fix checkstyle problem * add more test cases * optimize request/reply model * add examples to ProduceApplication.java * wrap RequestCallback to conceal RocketMQ message * requestCallback as method parameter * delete useless class * fix some comments and print format --- .../consumer/ConsumerWithReplyBytes.java | 39 ++ .../consumer/ConsumerWithReplyGeneric.java | 36 ++ .../consumer/ObjectConsumerWithReplyUser.java | 41 ++ .../springboot/consumer/StringConsumer.java | 2 +- .../StringConsumerWithReplyString.java | 37 ++ .../springboot/domain/ProductWithPayload.java | 54 ++ .../src/main/resources/application.properties | 9 +- .../springboot/ProducerApplication.java | 52 +- .../springboot/domain/ProductWithPayload.java | 54 ++ .../samples/springboot/domain/User.java | 48 +- .../src/main/resources/application.properties | 5 + .../RocketMQTransactionListener.java | 3 +- .../ListenerContainerConfiguration.java | 25 +- .../core/RocketMQLocalRequestCallback.java | 29 + .../spring/core/RocketMQReplyListener.java | 32 ++ .../spring/core/RocketMQTemplate.java | 527 ++++++++++++++++-- .../DefaultRocketMQListenerContainer.java | 218 +++++--- .../support/RocketMQListenerContainer.java | 6 - .../RocketMQAutoConfigurationTest.java | 69 +++ .../spring/core/RocketMQTemplateTest.java | 108 ++++ .../DefaultRocketMQListenerContainerTest.java | 98 ++++ 21 files changed, 1331 insertions(+), 161 deletions(-) create mode 100644 rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyBytes.java create mode 100644 rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyGeneric.java create mode 100644 rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ObjectConsumerWithReplyUser.java create mode 100644 rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerWithReplyString.java create mode 100644 rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/ProductWithPayload.java create mode 100644 rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/ProductWithPayload.java create mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalRequestCallback.java create mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQReplyListener.java diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyBytes.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyBytes.java new file mode 100644 index 00000000..850fbd33 --- /dev/null +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyBytes.java @@ -0,0 +1,39 @@ +/* + * 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.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQReplyListener; +import org.springframework.messaging.Message; +import org.springframework.messaging.support.MessageBuilder; +import org.springframework.stereotype.Service; + +/** + * The consumer that replying bytes + */ +@Service +@RocketMQMessageListener(topic = "${demo.rocketmq.bytesRequestTopic}", consumerGroup = "${demo.rocketmq.bytesRequestConsumer}", selectorExpression = "${demo.rocketmq.tag}") +public class ConsumerWithReplyBytes implements RocketMQReplyListener { + + @Override + public byte[] onMessage(MessageExt message) { + System.out.printf("------- ConsumerWithReplyBytes received: %s \n", message); + return "reply message content".getBytes(); + } +} diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyGeneric.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyGeneric.java new file mode 100644 index 00000000..e17e6751 --- /dev/null +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyGeneric.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.ProductWithPayload; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQReplyListener; +import org.springframework.stereotype.Service; + +/** + * The consumer that replying generic type + */ +@Service +@RocketMQMessageListener(topic = "${demo.rocketmq.genericRequestTopic}", consumerGroup = "${demo.rocketmq.genericRequestConsumer}", selectorExpression = "${demo.rocketmq.tag}") +public class ConsumerWithReplyGeneric implements RocketMQReplyListener> { + @Override + public ProductWithPayload onMessage(String message) { + System.out.printf("------- ConsumerWithReplyGeneric received: %s \n", message); + return new ProductWithPayload("replyProductName", "product payload"); + } +} diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ObjectConsumerWithReplyUser.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ObjectConsumerWithReplyUser.java new file mode 100644 index 00000000..f66b003b --- /dev/null +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ObjectConsumerWithReplyUser.java @@ -0,0 +1,41 @@ +/* + * 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.common.message.MessageExt; +import org.apache.rocketmq.samples.springboot.domain.User; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQReplyListener; +import org.springframework.stereotype.Service; + +/** + * The consumer that replying Object + */ +@Service +@RocketMQMessageListener(topic = "${demo.rocketmq.objectRequestTopic}", consumerGroup = "${demo.rocketmq.objectRequestConsumer}", selectorExpression = "${demo.rocketmq.tag}") +public class ObjectConsumerWithReplyUser implements RocketMQReplyListener { + + @Override + public User onMessage(User user) { + System.out.printf("------- ObjectConsumerWithReplyUser received: %s \n", user); + User replyUser = new User(); + replyUser.setUserAge((byte) 10); + replyUser.setUserName("replyUserName"); + return replyUser; + } +} 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 3801d484..11ac4890 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 @@ -22,7 +22,7 @@ import org.springframework.stereotype.Service; /** - * RocketMQMessageListener + * StringConsumer */ @Service @RocketMQMessageListener(topic = "${demo.rocketmq.topic}", consumerGroup = "string_consumer", selectorExpression = "${demo.rocketmq.tag}") diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerWithReplyString.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerWithReplyString.java new file mode 100644 index 00000000..b194bc6e --- /dev/null +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerWithReplyString.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.samples.springboot.consumer; + +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQReplyListener; +import org.springframework.stereotype.Service; + +/** + * The consumer that replying String + */ +@Service +@RocketMQMessageListener(topic = "${demo.rocketmq.stringRequestTopic}", consumerGroup = "${demo.rocketmq.stringRequestConsumer}", selectorExpression = "${demo.rocketmq.tag}") +public class StringConsumerWithReplyString implements RocketMQReplyListener { + + @Override + public String onMessage(String message) { + System.out.printf("------- StringConsumerWithReplyString received: %s \n", message); + return "reply string"; + } +} diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/ProductWithPayload.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/ProductWithPayload.java new file mode 100644 index 00000000..e2419299 --- /dev/null +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/ProductWithPayload.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; + +public class ProductWithPayload { + private String productName; + private T payload; + + public ProductWithPayload() { + } + + public ProductWithPayload(String productName, T payload) { + this.productName = productName; + this.payload = payload; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public T getPayload() { + return payload; + } + + public void setPayload(T payload) { + this.payload = payload; + } + + @Override public String toString() { + return "ProductWithPayload{" + + "productName='" + productName + '\'' + + ", payload=" + payload + + '}'; + } +} \ No newline at end of file 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 b2b2690b..5be0358d 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,9 +1,16 @@ spring.application.name=rocketmq-consume-demo rocketmq.name-server=localhost:9876 - # properties used in application code demo.rocketmq.topic=string-topic +demo.rocketmq.bytesRequestTopic=bytesRequestTopic +demo.rocketmq.stringRequestTopic=stringRequestTopic +demo.rocketmq.objectRequestTopic=objectRequestTopic +demo.rocketmq.genericRequestTopic=genericRequestTopic +demo.rocketmq.bytesRequestConsumer=bytesRequestConsumer +demo.rocketmq.stringRequestConsumer=stringRequestConsumer +demo.rocketmq.objectRequestConsumer=objectRequestConsumer +demo.rocketmq.genericRequestConsumer=genericRequestConsumer 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 d914bb57..46ac5abe 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 @@ -17,6 +17,7 @@ package org.apache.rocketmq.samples.springboot; +import com.alibaba.fastjson.TypeReference; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; @@ -26,8 +27,10 @@ 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.samples.springboot.domain.ProductWithPayload; import org.apache.rocketmq.samples.springboot.domain.User; import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQLocalRequestCallback; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; import org.apache.rocketmq.spring.core.RocketMQTemplate; @@ -60,6 +63,15 @@ public class ProducerApplication implements CommandLineRunner { private String orderPaidTopic; @Value("${demo.rocketmq.msgExtTopic}") private String msgExtTopic; + @Value("${demo.rocketmq.stringRequestTopic}") + private String stringRequestTopic; + @Value("${demo.rocketmq.bytesRequestTopic}") + private String bytesRequestTopic; + @Value("${demo.rocketmq.objectRequestTopic}") + private String objectRequestTopic; + @Value("${demo.rocketmq.genericRequestTopic}") + private String genericRequestTopic; + @Resource(name = "extRocketMQTemplate") private RocketMQTemplate extRocketMQTemplate; @@ -116,6 +128,45 @@ public void onException(Throwable var1) { // Send transactional messages using extRocketMQTemplate testExtRocketMQTemplateTransaction(); + + // Send request in sync mode and receive a reply of String type. + String replyString = rocketMQTemplate.sendAndReceive(stringRequestTopic, "request string", String.class); + System.out.printf("send %s and receive %s %n", "request string", replyString); + + // Send request in sync mode with timeout parameter and receive a reply of byte[] type. + byte[] replyBytes = rocketMQTemplate.sendAndReceive(bytesRequestTopic, MessageBuilder.withPayload("request byte[]").build(), byte[].class, 3000); + System.out.printf("send %s and receive %s %n", "request byte[]", new String(replyBytes)); + + // Send request in sync mode with hashKey parameter and receive a reply of User type. + User requestUser = new User().setUserAge((byte) 9).setUserName("requestUserName"); + User replyUser = rocketMQTemplate.sendAndReceive(objectRequestTopic, requestUser, User.class, "order-id"); + System.out.printf("send %s and receive %s %n", requestUser, replyUser); + // Send request in sync mode with timeout and delayLevel parameter parameter and receive a reply of generic type. + ProductWithPayload replyGenericObject = rocketMQTemplate.sendAndReceive(genericRequestTopic, "request generic", + new TypeReference>() { + }.getType(), 30000, 2); + System.out.printf("send %s and receive %s %n", "request generic", replyGenericObject); + + // Send request in async mode and receive a reply of String type. + rocketMQTemplate.sendAndReceive(stringRequestTopic, "request string", new RocketMQLocalRequestCallback() { + @Override public void onSuccess(String message) { + System.out.printf("send %s and receive %s %n", "request string", message); + } + + @Override public void onException(Throwable e) { + e.printStackTrace(); + } + }); + // Send request in async mode and receive a reply of User type. + rocketMQTemplate.sendAndReceive(objectRequestTopic, new User().setUserAge((byte) 9).setUserName("requestUserName"), new RocketMQLocalRequestCallback() { + @Override public void onSuccess(User message) { + System.out.printf("send user object and receive %s %n", message.toString()); + } + + @Override public void onException(Throwable e) { + e.printStackTrace(); + } + }, 5000); } private void testBatchMessages() { @@ -237,5 +288,4 @@ public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { return RocketMQLocalTransactionState.COMMIT; } } - } diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/ProductWithPayload.java b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/ProductWithPayload.java new file mode 100644 index 00000000..e2419299 --- /dev/null +++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/ProductWithPayload.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; + +public class ProductWithPayload { + private String productName; + private T payload; + + public ProductWithPayload() { + } + + public ProductWithPayload(String productName, T payload) { + this.productName = productName; + this.payload = payload; + } + + public String getProductName() { + return productName; + } + + public void setProductName(String productName) { + this.productName = productName; + } + + public T getPayload() { + return payload; + } + + public void setPayload(T payload) { + this.payload = payload; + } + + @Override public String toString() { + return "ProductWithPayload{" + + "productName='" + productName + '\'' + + ", payload=" + payload + + '}'; + } +} \ No newline at end of file diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/User.java b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/User.java index 42acc11e..4f2579f6 100644 --- a/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/User.java +++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/User.java @@ -18,32 +18,32 @@ package org.apache.rocketmq.samples.springboot.domain; public class User { - private String userName; - private Byte userAge; + private String userName; + private Byte userAge; - public String getUserName() { - return userName; - } + public String getUserName() { + return userName; + } - public User setUserName(String userName) { - this.userName = userName; - return this; - } + public User setUserName(String userName) { + this.userName = userName; + return this; + } - public Byte getUserAge() { - return userAge; - } + public Byte getUserAge() { + return userAge; + } - public User setUserAge(Byte userAge) { - this.userAge = userAge; - return this; - } + public User setUserAge(Byte userAge) { + this.userAge = userAge; + return this; + } - @Override - public String toString() { - return "User{" + - "userName='" + userName + '\'' + - ", userAge=" + userAge + - '}'; - } - } \ No newline at end of file + @Override + public String toString() { + return "User{" + + "userName='" + userName + '\'' + + ", userAge=" + userAge + + '}'; + } +} \ No newline at end of file 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 27a3abc2..c68ac3a0 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 @@ -9,4 +9,9 @@ demo.rocketmq.msgExtTopic=message-ext-topic demo.rocketmq.transTopic=spring-transaction-topic demo.rocketmq.topic.user=user-topic +demo.rocketmq.bytesRequestTopic=bytesRequestTopic:tagA +demo.rocketmq.stringRequestTopic=stringRequestTopic:tagA +demo.rocketmq.objectRequestTopic=objectRequestTopic:tagA +demo.rocketmq.genericRequestTopic=genericRequestTopic:tagA + demo.rocketmq.extNameServer=127.0.0.1:9876 \ No newline at end of file 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 index dac280f4..0faa57a0 100644 --- 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 @@ -26,7 +26,8 @@ /** * This annotation is used over a class which implements interface - * org.apache.rocketmq.client.producer.TransactionListener. The class implements + * org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener, which will be converted to + * org.apache.rocketmq.client.producer.TransactionListener later. The class implements * two methods for process callback events after the txProducer sends a transactional message. *

Note: The annotation is used only on RocketMQ client producer side, it can not be used * on consumer side. diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index 7bda36cb..699474de 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -26,6 +26,7 @@ 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.core.RocketMQReplyListener; import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.slf4j.Logger; @@ -65,7 +66,7 @@ public ListenerContainerConfiguration(RocketMQMessageConverter rocketMQMessageCo @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = (ConfigurableApplicationContext)applicationContext; + this.applicationContext = (ConfigurableApplicationContext) applicationContext; } @Override @@ -80,8 +81,12 @@ public void afterSingletonsInstantiated() { private void registerContainer(String beanName, Object bean) { Class clazz = AopProxyUtils.ultimateTargetClass(bean); - if (!RocketMQListener.class.isAssignableFrom(bean.getClass())) { - throw new IllegalStateException(clazz + " is not instance of " + RocketMQListener.class.getName()); + if (RocketMQListener.class.isAssignableFrom(bean.getClass()) && RocketMQReplyListener.class.isAssignableFrom(bean.getClass())) { + throw new IllegalStateException(clazz + " cannot be both instance of " + RocketMQListener.class.getName() + " and " + RocketMQReplyListener.class.getName()); + } + + if (!RocketMQListener.class.isAssignableFrom(bean.getClass()) && !RocketMQReplyListener.class.isAssignableFrom(bean.getClass())) { + throw new IllegalStateException(clazz + " is not instance of " + RocketMQListener.class.getName() + " or " + RocketMQReplyListener.class.getName()); } RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class); @@ -90,7 +95,7 @@ private void registerContainer(String beanName, Object bean) { String topic = this.environment.resolvePlaceholders(annotation.topic()); boolean listenerEnabled = - (boolean)rocketMQProperties.getConsumer().getListeners().getOrDefault(consumerGroup, Collections.EMPTY_MAP) + (boolean) rocketMQProperties.getConsumer().getListeners().getOrDefault(consumerGroup, Collections.EMPTY_MAP) .getOrDefault(topic, true); if (!listenerEnabled) { @@ -103,7 +108,7 @@ private void registerContainer(String beanName, Object bean) { String containerBeanName = String.format("%s_%s", DefaultRocketMQListenerContainer.class.getName(), counter.incrementAndGet()); - GenericApplicationContext genericApplicationContext = (GenericApplicationContext)applicationContext; + GenericApplicationContext genericApplicationContext = (GenericApplicationContext) applicationContext; genericApplicationContext.registerBean(containerBeanName, DefaultRocketMQListenerContainer.class, () -> createRocketMQListenerContainer(containerBeanName, bean, annotation)); @@ -124,9 +129,9 @@ private void registerContainer(String beanName, Object bean) { private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String name, Object bean, RocketMQMessageListener annotation) { DefaultRocketMQListenerContainer container = new DefaultRocketMQListenerContainer(); - + container.setRocketMQMessageListener(annotation); - + String nameServer = environment.resolvePlaceholders(annotation.nameServer()); nameServer = StringUtils.isEmpty(nameServer) ? rocketMQProperties.getNameServer() : nameServer; String accessChannel = environment.resolvePlaceholders(annotation.accessChannel()); @@ -140,7 +145,11 @@ private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String container.setSelectorExpression(tags); } container.setConsumerGroup(environment.resolvePlaceholders(annotation.consumerGroup())); - container.setRocketMQListener((RocketMQListener)bean); + if (RocketMQListener.class.isAssignableFrom(bean.getClass())) { + container.setRocketMQListener((RocketMQListener) bean); + } else if (RocketMQReplyListener.class.isAssignableFrom(bean.getClass())) { + container.setRocketMQReplyListener((RocketMQReplyListener) bean); + } container.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); container.setName(name); // REVIEW ME, use the same clientId or multiple? diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalRequestCallback.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalRequestCallback.java new file mode 100644 index 00000000..56b15ff9 --- /dev/null +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalRequestCallback.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.core; + +/** + * Classes implementing this interface are used for processing callback events after receiving + * reply messages from consumers. + * + * @param the type of message that wanted to receive from consumer + */ +public interface RocketMQLocalRequestCallback { + void onSuccess(final T message); + + void onException(final Throwable e); +} diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQReplyListener.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQReplyListener.java new file mode 100644 index 00000000..916368d3 --- /dev/null +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQReplyListener.java @@ -0,0 +1,32 @@ +/* + * 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; + +/** + * The consumer supporting request-reply should implement this interface. + * + * @param the type of data received by the listener + * @param the type of data replying to producer + */ +public interface RocketMQReplyListener { + /** + * @param message data received by the listener + * @return data replying to producer + */ + R onMessage(T message); +} 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 c655696e..089016a9 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 @@ -17,6 +17,9 @@ package org.apache.rocketmq.spring.core; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.Map; @@ -24,19 +27,24 @@ 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.RequestCallback; 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.common.message.MessageExt; +import org.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.apache.rocketmq.spring.support.RocketMQUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.aop.framework.AopProxyUtils; 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.converter.SmartMessageConverter; import org.springframework.messaging.core.AbstractMessageSendingTemplate; import org.springframework.messaging.core.MessagePostProcessor; import org.springframework.messaging.support.MessageBuilder; @@ -52,6 +60,8 @@ public class RocketMQTemplate extends AbstractMessageSendingTemplate imp private MessageQueueSelector messageQueueSelector = new SelectMessageQueueByHash(); + private RocketMQMessageConverter rocketMQMessageConverter = new RocketMQMessageConverter(); + public DefaultMQProducer getProducer() { return producer; } @@ -76,6 +86,356 @@ public void setMessageQueueSelector(MessageQueueSelector messageQueueSelector) { this.messageQueueSelector = messageQueueSelector; } + /** + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @return + */ + public T sendAndReceive(String destination, Message message, Type type) { + return sendAndReceive(destination, message, type, null, producer.getSendMsgTimeout(), 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param type The type of T + * @return + */ + public T sendAndReceive(String destination, Object payload, Type type) { + return sendAndReceive(destination, payload, type, null, producer.getSendMsgTimeout(), 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param timeout send timeout in millis + * @return + */ + public T sendAndReceive(String destination, Message message, Type type, long timeout) { + return sendAndReceive(destination, message, type, null, timeout, 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param type The type of T + * @param timeout send timeout in millis + * @return + */ + public T sendAndReceive(String destination, Object payload, Type type, long timeout) { + return sendAndReceive(destination, payload, type, null, timeout, 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) + * @return + */ + public T sendAndReceive(String destination, Message message, Type type, long timeout, int delayLevel) { + return sendAndReceive(destination, message, type, null, timeout, delayLevel); + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param type The type of T + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) + * @return + */ + public T sendAndReceive(String destination, Object payload, Type type, long timeout, int delayLevel) { + return sendAndReceive(destination, payload, type, null, timeout, delayLevel); + } + + /** + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param hashKey needed when sending message orderly + * @return + */ + public T sendAndReceive(String destination, Message message, Type type, String hashKey) { + return sendAndReceive(destination, message, type, hashKey, producer.getSendMsgTimeout(), 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param type The type of T + * @param hashKey needed when sending message orderly + * @return + */ + public T sendAndReceive(String destination, Object payload, Type type, String hashKey) { + return sendAndReceive(destination, payload, type, hashKey, producer.getSendMsgTimeout(), 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @return + */ + public T sendAndReceive(String destination, Message message, Type type, String hashKey, long timeout) { + return sendAndReceive(destination, message, type, hashKey, timeout, 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param type The type of T + * @param hashKey + * @return + */ + public T sendAndReceive(String destination, Object payload, Type type, String hashKey, long timeout) { + return sendAndReceive(destination, payload, type, hashKey, timeout, 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type that receive + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) + * @return + */ + public T sendAndReceive(String destination, Message message, Type type, String hashKey, + long timeout, int delayLevel) { + if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { + log.error("send request message failed. destination:{}, message is null ", destination); + throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); + } + + try { + org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); + if (delayLevel > 0) { + rocketMsg.setDelayTimeLevel(delayLevel); + } + MessageExt replyMessage; + + if (Objects.isNull(hashKey) || hashKey.isEmpty()) { + replyMessage = (MessageExt) producer.request(rocketMsg, timeout); + } else { + replyMessage = (MessageExt) producer.request(rocketMsg, messageQueueSelector, hashKey, timeout); + } + return replyMessage != null ? (T) doConvertMessage(replyMessage, type) : null; + } catch (Exception e) { + log.error("send request message failed. destination:{}, message:{} ", destination, message); + throw new MessagingException(e.getMessage(), e); + } + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param type The type that receive + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) + * @return + */ + public T sendAndReceive(String destination, Object payload, Type type, String hashKey, + long timeout, int delayLevel) { + Message message = MessageBuilder.withPayload(payload).build(); + return sendAndReceive(destination, message, type, hashKey, timeout, delayLevel); + } + + /** + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @return + */ + public void sendAndReceive(String destination, Message message, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback) { + sendAndReceive(destination, message, rocketMQLocalRequestCallback, null, producer.getSendMsgTimeout(), 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @return + */ + public void sendAndReceive(String destination, Object payload, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback) { + sendAndReceive(destination, payload, rocketMQLocalRequestCallback, null, producer.getSendMsgTimeout(), 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @param timeout send timeout in millis + * @return + */ + public void sendAndReceive(String destination, Message message, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback, long timeout) { + sendAndReceive(destination, message, rocketMQLocalRequestCallback, null, timeout, 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @param timeout send timeout in millis + * @return + */ + public void sendAndReceive(String destination, Object payload, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback, long timeout) { + sendAndReceive(destination, payload, rocketMQLocalRequestCallback, null, timeout, 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) + * @return + */ + public void sendAndReceive(String destination, Message message, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback, long timeout, int delayLevel) { + sendAndReceive(destination, message, rocketMQLocalRequestCallback, null, timeout, delayLevel); + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @param hashKey needed when sending message orderly + * @return + */ + public void sendAndReceive(String destination, Object payload, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback, String hashKey) { + sendAndReceive(destination, payload, rocketMQLocalRequestCallback, hashKey, producer.getSendMsgTimeout(), 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @return + */ + public void sendAndReceive(String destination, Message message, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback, String hashKey, long timeout) { + sendAndReceive(destination, message, rocketMQLocalRequestCallback, hashKey, timeout, 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @return + */ + public void sendAndReceive(String destination, Object payload, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback, String hashKey, long timeout) { + sendAndReceive(destination, payload, rocketMQLocalRequestCallback, hashKey, timeout, 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @param hashKey needed when sending message orderly + * @return + */ + public void sendAndReceive(String destination, Message message, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback, String hashKey) { + sendAndReceive(destination, message, rocketMQLocalRequestCallback, hashKey, producer.getSendMsgTimeout(), 0); + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) + * @return + */ + public void sendAndReceive(String destination, Object payload, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback, long timeout, int delayLevel) { + sendAndReceive(destination, payload, rocketMQLocalRequestCallback, null, timeout, delayLevel); + } + + /** + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) + * @return + */ + public void sendAndReceive(String destination, Object payload, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback, String hashKey, long timeout, int delayLevel) { + Message message = MessageBuilder.withPayload(payload).build(); + sendAndReceive(destination, message, rocketMQLocalRequestCallback, hashKey, timeout, delayLevel); + } + + /** + * Send request message in asynchronous mode.

This method returns immediately. On receiving reply message, + * rocketMQLocalRequestCallback will be executed.

+ * + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) + * @return + */ + public void sendAndReceive(String destination, Message message, + RocketMQLocalRequestCallback rocketMQLocalRequestCallback, String hashKey, long timeout, int delayLevel) { + if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { + log.error("send request message failed. destination:{}, message is null ", destination); + throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); + } + + try { + org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); + if (delayLevel > 0) { + rocketMsg.setDelayTimeLevel(delayLevel); + } + if (timeout <= 0) { + timeout = producer.getSendMsgTimeout(); + } + RequestCallback requestCallback = null; + if (rocketMQLocalRequestCallback != null) { + requestCallback = new RequestCallback() { + @Override public void onSuccess(org.apache.rocketmq.common.message.Message message) { + rocketMQLocalRequestCallback.onSuccess(doConvertMessage((MessageExt) message, getMessageType(rocketMQLocalRequestCallback))); + } + + @Override public void onException(Throwable e) { + rocketMQLocalRequestCallback.onException(e); + } + }; + } + if (Objects.isNull(hashKey) || hashKey.isEmpty()) { + producer.request(rocketMsg, requestCallback, timeout); + } else { + producer.request(rocketMsg, messageQueueSelector, hashKey, requestCallback, timeout); + } + } catch ( + Exception e) { + log.error("send request message failed. destination:{}, message:{} ", destination, message); + throw new MessagingException(e.getMessage(), e); + } + + } + /** *

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 @@ -87,7 +447,7 @@ public void setMessageQueueSelector(MessageQueueSelector messageQueueSelector) { * duplication issue. * * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} + * @param message {@link org.springframework.messaging.Message} * @return {@link SendResult} */ public SendResult syncSend(String destination, Message message) { @@ -98,8 +458,8 @@ public SendResult syncSend(String destination, Message message) { * 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 message {@link org.springframework.messaging.Message} + * @param timeout send timeout with millis * @return {@link SendResult} */ public SendResult syncSend(String destination, Message message, long timeout) { @@ -110,8 +470,8 @@ public SendResult syncSend(String destination, Message message, long timeout) * syncSend batch messages in a given timeout. * * @param destination formats: `topicName:tags` - * @param messages Collection of {@link org.springframework.messaging.Message} - * @param timeout send timeout with millis + * @param messages Collection of {@link org.springframework.messaging.Message} + * @param timeout send timeout with millis * @return {@link SendResult} */ public SendResult syncSend(String destination, Collection messages, long timeout) { @@ -147,9 +507,9 @@ public SendResult syncSend(String destination, Collection * 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 + * @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) { @@ -179,7 +539,7 @@ public SendResult syncSend(String destination, Message message, long timeout, * Same to {@link #syncSend(String, Message)}. * * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @param payload the Object to use as payload * @return {@link SendResult} */ public SendResult syncSend(String destination, Object payload) { @@ -190,8 +550,8 @@ public SendResult syncSend(String destination, Object payload) { * 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 + * @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) { @@ -203,8 +563,8 @@ public SendResult syncSend(String destination, Object payload, long 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 ... + * @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) { @@ -215,9 +575,9 @@ public SendResult syncSendOrderly(String destination, Message message, String * 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 + * @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) { @@ -244,8 +604,8 @@ public SendResult syncSendOrderly(String destination, Message message, String * 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 ... + * @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) { @@ -256,9 +616,9 @@ public SendResult syncSendOrderly(String destination, Object payload, String has * 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 + * @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) { @@ -270,11 +630,11 @@ public SendResult syncSendOrderly(String destination, Object payload, String has * Same to {@link #asyncSend(String, Message, SendCallback)} with send timeout and delay level specified in * addition. * - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} * @param sendCallback {@link SendCallback} - * @param timeout send timeout with millis - * @param delayLevel level for the delay message + * @param timeout send timeout with millis + * @param delayLevel level for the delay message */ public void asyncSend(String destination, Message message, SendCallback sendCallback, long timeout, int delayLevel) { @@ -297,10 +657,10 @@ public void asyncSend(String destination, Message message, SendCallback sendC /** * 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 destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} * @param sendCallback {@link SendCallback} - * @param timeout send timeout with millis + * @param timeout send timeout with millis */ public void asyncSend(String destination, Message message, SendCallback sendCallback, long timeout) { asyncSend(destination, message, sendCallback, timeout, 0); @@ -316,8 +676,8 @@ public void asyncSend(String destination, Message message, SendCallback sendC * 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 destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} * @param sendCallback {@link SendCallback} */ public void asyncSend(String destination, Message message, SendCallback sendCallback) { @@ -327,10 +687,10 @@ public void asyncSend(String destination, Message message, SendCallback sendC /** * 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 destination formats: `topicName:tags` + * @param payload the Object to use as payload * @param sendCallback {@link SendCallback} - * @param timeout send timeout with millis + * @param timeout send timeout with millis */ public void asyncSend(String destination, Object payload, SendCallback sendCallback, long timeout) { Message message = MessageBuilder.withPayload(payload).build(); @@ -340,8 +700,8 @@ public void asyncSend(String destination, Object payload, SendCallback sendCallb /** * Same to {@link #asyncSend(String, Message, SendCallback)}. * - * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @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) { @@ -352,11 +712,11 @@ public void asyncSend(String destination, Object payload, SendCallback sendCallb * 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 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 + * @param timeout send timeout with millis */ public void asyncSendOrderly(String destination, Message message, String hashKey, SendCallback sendCallback, long timeout) { @@ -376,9 +736,9 @@ public void asyncSendOrderly(String destination, Message message, String hash /** * 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 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) { @@ -388,9 +748,9 @@ public void asyncSendOrderly(String destination, Message message, String hash /** * 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 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) { @@ -400,11 +760,11 @@ public void asyncSendOrderly(String destination, Object payload, String hashKey, /** * 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 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 + * @param timeout send timeout with millis */ public void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback, long timeout) { @@ -419,7 +779,7 @@ public void asyncSendOrderly(String destination, Object payload, String hashKey, * 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} + * @param message {@link org.springframework.messaging.Message} */ public void sendOneWay(String destination, Message message) { if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { @@ -439,7 +799,7 @@ public void sendOneWay(String destination, Message message) { * Same to {@link #sendOneWay(String, Message)} * * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @param payload the Object to use as payload */ public void sendOneWay(String destination, Object payload) { Message message = MessageBuilder.withPayload(payload).build(); @@ -450,8 +810,8 @@ public void sendOneWay(String destination, Object payload) { * 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 ... + * @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())) { @@ -471,7 +831,7 @@ public void sendOneWayOrderly(String destination, Message message, String has * Same to {@link #sendOneWayOrderly(String, Message, String)} * * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @param payload the Object to use as payload */ public void sendOneWayOrderly(String destination, Object payload, String hashKey) { Message message = MessageBuilder.withPayload(payload).build(); @@ -511,9 +871,9 @@ public void destroy() { /** * Send Spring Message in Transaction * - * @param destination destination formats: `topicName:tags` - * @param message message {@link org.springframework.messaging.Message} - * @param arg ext arg + * @param destination destination formats: `topicName:tags` + * @param message message {@link org.springframework.messaging.Message} + * @param arg ext arg * @return TransactionSendResult * @throws MessagingException */ @@ -537,4 +897,57 @@ private org.apache.rocketmq.common.message.Message createRocketMqMessage( destination, msg); } + private Object doConvertMessage(MessageExt messageExt, Type type) { + if (Objects.equals(type, MessageExt.class)) { + return messageExt; + } else if (Objects.equals(type, byte[].class)) { + return messageExt.getBody(); + } else { + String str = new String(messageExt.getBody(), Charset.forName(charset)); + if (Objects.equals(type, String.class)) { + return str; + } else { + // If msgType not string, use objectMapper change it. + try { + if (type instanceof Class) { + //if the messageType has not Generic Parameter + return this.getMessageConverter().fromMessage(MessageBuilder.withPayload(str).build(), (Class) type); + } else { + //if the messageType has Generic Parameter, then use SmartMessageConverter#fromMessage with third parameter "conversionHint". + //we have validate the MessageConverter is SmartMessageConverter in this#getMethodParameter. + return ((SmartMessageConverter) this.getMessageConverter()).fromMessage(MessageBuilder.withPayload(str).build(), (Class) ((ParameterizedType) type).getRawType(), null); + } + } catch (Exception e) { + log.error("convert failed. str:{}, msgType:{}", str, type); + throw new RuntimeException("cannot convert message to " + type, e); + } + } + } + } + + private Type getMessageType(RocketMQLocalRequestCallback rocketMQLocalRequestCallback) { + Class targetClass = AopProxyUtils.ultimateTargetClass(rocketMQLocalRequestCallback); + Type matchedGenericInterface = null; + while (Objects.nonNull(targetClass)) { + Type[] interfaces = targetClass.getGenericInterfaces(); + if (Objects.nonNull(interfaces)) { + for (Type type : interfaces) { + if (type instanceof ParameterizedType && (Objects.equals(((ParameterizedType) type).getRawType(), RocketMQLocalRequestCallback.class))) { + matchedGenericInterface = type; + break; + } + } + } + targetClass = targetClass.getSuperclass(); + } + if (Objects.isNull(matchedGenericInterface)) { + return Object.class; + } + + Type[] actualTypeArguments = ((ParameterizedType) matchedGenericInterface).getActualTypeArguments(); + if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) { + return actualTypeArguments[0]; + } + return Object.class; + } } 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 25ec3208..2642d07b 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 @@ -34,14 +34,20 @@ import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely; import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.client.producer.SendStatus; +import org.apache.rocketmq.client.utils.MessageUtil; import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.remoting.RPCHook; +import org.apache.rocketmq.remoting.exception.RemotingException; 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.apache.rocketmq.spring.core.RocketMQReplyListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; @@ -51,10 +57,14 @@ import org.springframework.context.ApplicationContextAware; import org.springframework.context.SmartLifecycle; import org.springframework.core.MethodParameter; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHeaders; +import org.springframework.messaging.converter.MessageConversionException; import org.springframework.messaging.converter.MessageConverter; import org.springframework.messaging.converter.SmartMessageConverter; import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.Assert; +import org.springframework.util.MimeTypeUtils; @SuppressWarnings("WeakerAccess") public class DefaultRocketMQListenerContainer implements InitializingBean, @@ -92,6 +102,8 @@ public class DefaultRocketMQListenerContainer implements InitializingBean, private RocketMQListener rocketMQListener; + private RocketMQReplyListener rocketMQReplyListener; + private RocketMQMessageListener rocketMQMessageListener; private DefaultMQPushConsumer consumer; @@ -186,6 +198,14 @@ public void setRocketMQListener(RocketMQListener rocketMQListener) { this.rocketMQListener = rocketMQListener; } + public RocketMQReplyListener getRocketMQReplyListener() { + return rocketMQReplyListener; + } + + public void setRocketMQReplyListener(RocketMQReplyListener rocketMQReplyListener) { + this.rocketMQReplyListener = rocketMQReplyListener; + } + public RocketMQMessageListener getRocketMQMessageListener() { return rocketMQMessageListener; } @@ -209,14 +229,14 @@ public SelectorType getSelectorType() { return selectorType; } - public String getSelectorExpression() { - return selectorExpression; - } - public void setSelectorExpression(String selectorExpression) { this.selectorExpression = selectorExpression; } + public String getSelectorExpression() { + return selectorExpression; + } + public MessageModel getMessageModel() { return messageModel; } @@ -229,11 +249,6 @@ public void setConsumer(DefaultMQPushConsumer consumer) { this.consumer = consumer; } - @Override - public void setupMessageListener(RocketMQListener rocketMQListener) { - this.rocketMQListener = rocketMQListener; - } - @Override public void destroy() { this.setRunning(false); @@ -327,6 +342,119 @@ public void setName(String name) { this.name = name; } + public class DefaultMessageListenerConcurrently implements MessageListenerConcurrently { + + @SuppressWarnings("unchecked") + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + for (MessageExt messageExt : msgs) { + log.debug("received msg: {}", messageExt); + try { + long now = System.currentTimeMillis(); + handleMessage(messageExt); + long costTime = System.currentTimeMillis() - now; + log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime); + } catch (Exception e) { + log.warn("consume message failed. messageExt:{}, error:{}", messageExt, e); + context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + } + + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + } + + public class DefaultMessageListenerOrderly implements MessageListenerOrderly { + + @SuppressWarnings("unchecked") + @Override + public ConsumeOrderlyStatus consumeMessage(List msgs, ConsumeOrderlyContext context) { + for (MessageExt messageExt : msgs) { + log.debug("received msg: {}", messageExt); + try { + long now = System.currentTimeMillis(); + handleMessage(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; + } + } + + private void handleMessage( + MessageExt messageExt) throws MQClientException, RemotingException, InterruptedException { + if (rocketMQListener != null) { + rocketMQListener.onMessage(doConvertMessage(messageExt)); + } else if (rocketMQReplyListener != null) { + Object replyContent = rocketMQReplyListener.onMessage(doConvertMessage(messageExt)); + Message message = MessageBuilder.withPayload(replyContent).build(); + + org.apache.rocketmq.common.message.Message replyMessage = MessageUtil.createReplyMessage(messageExt, convertToBytes(message)); + consumer.getDefaultMQPushConsumerImpl().getmQClientFactory().getDefaultMQProducer().send(replyMessage, new SendCallback() { + @Override public void onSuccess(SendResult sendResult) { + if (sendResult.getSendStatus() != SendStatus.SEND_OK) { + log.error("Consumer replies message failed. SendStatus: {}", sendResult.getSendStatus()); + } else { + log.info("Consumer replies message success."); + } + } + + @Override public void onException(Throwable e) { + log.error("Consumer replies message failed. error: {}", e.getLocalizedMessage()); + } + }); + } + } + + private byte[] convertToBytes(Message message) { + Message messageWithSerializedPayload = doConvert(message.getPayload(), message.getHeaders()); + Object payloadObj = messageWithSerializedPayload.getPayload(); + byte[] payloads; + try { + if (null == payloadObj) { + throw new RuntimeException("the message cannot be empty"); + } + if (payloadObj instanceof String) { + payloads = ((String) payloadObj).getBytes(Charset.forName(charset)); + } else if (payloadObj instanceof byte[]) { + payloads = (byte[]) messageWithSerializedPayload.getPayload(); + } else { + String jsonObj = (String) this.messageConverter.fromMessage(messageWithSerializedPayload, payloadObj.getClass()); + if (null == jsonObj) { + throw new RuntimeException(String.format( + "empty after conversion [messageConverter:%s,payloadClass:%s,payloadObj:%s]", + this.messageConverter.getClass(), payloadObj.getClass(), payloadObj)); + } + payloads = jsonObj.getBytes(Charset.forName(charset)); + } + } catch (Exception e) { + throw new RuntimeException("convert to bytes failed.", e); + } + return payloads; + } + + private Message doConvert(Object payload, MessageHeaders headers) { + Message message = this.messageConverter instanceof SmartMessageConverter ? + ((SmartMessageConverter) this.messageConverter).toMessage(payload, headers, null) : + this.messageConverter.toMessage(payload, headers); + if (message == null) { + String payloadType = payload.getClass().getName(); + Object contentType = headers != null ? headers.get(MessageHeaders.CONTENT_TYPE) : null; + throw new MessageConversionException("Unable to convert payload with type='" + payloadType + + "', contentType='" + contentType + "', converter=[" + this.messageConverter + "]"); + } + MessageBuilder builder = MessageBuilder.fromMessage(message); + builder.setHeaderIfAbsent(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN); + return builder.build(); + } + @SuppressWarnings("unchecked") private Object doConvertMessage(MessageExt messageExt) { if (Objects.equals(messageType, MessageExt.class)) { @@ -355,7 +483,12 @@ private Object doConvertMessage(MessageExt messageExt) { } private MethodParameter getMethodParameter() { - Class targetClass = AopProxyUtils.ultimateTargetClass(rocketMQListener); + Class targetClass; + if (rocketMQListener != null) { + targetClass = AopProxyUtils.ultimateTargetClass(rocketMQListener); + } else { + targetClass = AopProxyUtils.ultimateTargetClass(rocketMQReplyListener); + } Type messageType = this.getMessageType(); Class clazz = null; if (messageType instanceof ParameterizedType && messageConverter instanceof SmartMessageConverter) { @@ -375,14 +508,19 @@ private MethodParameter getMethodParameter() { } private Type getMessageType() { - Class targetClass = AopProxyUtils.ultimateTargetClass(rocketMQListener); + Class targetClass; + if (rocketMQListener != null) { + targetClass = AopProxyUtils.ultimateTargetClass(rocketMQListener); + } else { + targetClass = AopProxyUtils.ultimateTargetClass(rocketMQReplyListener); + } Type matchedGenericInterface = null; while (Objects.nonNull(targetClass)) { Type[] interfaces = targetClass.getGenericInterfaces(); if (Objects.nonNull(interfaces)) { for (Type type : interfaces) { - if (type instanceof ParameterizedType - && Objects.equals(((ParameterizedType) type).getRawType(), RocketMQListener.class)) { + if (type instanceof ParameterizedType && + (Objects.equals(((ParameterizedType) type).getRawType(), RocketMQListener.class) || Objects.equals(((ParameterizedType) type).getRawType(), RocketMQReplyListener.class))) { matchedGenericInterface = type; break; } @@ -401,10 +539,10 @@ private Type getMessageType() { return Object.class; } - - private void initRocketMQPushConsumer() throws MQClientException { - Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); + if (rocketMQListener == null && rocketMQReplyListener == null) { + throw new IllegalArgumentException("Property 'rocketMQListener' or 'rocketMQReplyListener' is required"); + } Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); Assert.notNull(nameServer, "Property 'nameServer' is required"); Assert.notNull(topic, "Property 'topic' is required"); @@ -475,54 +613,10 @@ private void initRocketMQPushConsumer() throws MQClientException { if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) { ((RocketMQPushConsumerLifecycleListener) rocketMQListener).prepareStart(consumer); + } else if (rocketMQReplyListener instanceof RocketMQPushConsumerLifecycleListener) { + ((RocketMQPushConsumerLifecycleListener) rocketMQReplyListener).prepareStart(consumer); } } - public class DefaultMessageListenerConcurrently implements MessageListenerConcurrently { - - @SuppressWarnings("unchecked") - @Override - public ConsumeConcurrentlyStatus consumeMessage(List 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") - @Override - public ConsumeOrderlyStatus consumeMessage(List 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; - } - } - } 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 index ee52de80..d9693bc8 100644 --- 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 @@ -17,14 +17,8 @@ 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/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index 553183d1..18a32f82 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -27,6 +27,7 @@ import org.apache.rocketmq.spring.core.RocketMQListener; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; +import org.apache.rocketmq.spring.core.RocketMQReplyListener; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.junit.Assert; @@ -183,6 +184,24 @@ public void testRocketMQListenerContainer() { }); } + @Test + public void testRocketMQListenerContainer_RocketMQReplyListener() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). + withUserConfiguration(TestConfigWithRocketMQReplyListener.class). + run((context) -> { + assertThat(context).getFailure().hasMessageContaining("connect to [127.0.0.1:9876] failed"); + }); + } + + @Test(expected = IllegalStateException.class) + public void testRocketMQListenerContainer_WrongRocketMQListenerType() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). + withUserConfiguration(TestConfigWithWrongRocketMQListener.class). + run((context) -> { + context.getBean(RocketMQMessageConverter.class); + }); + } + @Configuration static class TestConfig { @@ -198,6 +217,30 @@ public Object consumeListener1() { } + @Configuration + static class TestConfigWithRocketMQReplyListener { + + @Bean + public Object consumeListener() { + return new TestDefaultNameServerRocketMQReplyListener(); + } + + @Bean + public Object consumeListener1() { + return new TestCustomNameServerRocketMQReplyListener(); + } + + } + + @Configuration + static class TestConfigWithWrongRocketMQListener { + + @Bean + public Object consumeListener() { + return new WrongRocketMQListener(); + } + } + @Configuration static class CustomObjectMapperConfig { @@ -236,6 +279,32 @@ public void onMessage(Object message) { } } + @RocketMQMessageListener(consumerGroup = "abcd", topic = "test") + static class TestDefaultNameServerRocketMQReplyListener implements RocketMQReplyListener { + + @Override + public String onMessage(String message) { + return "test"; + } + } + + @RocketMQMessageListener(consumerGroup = "abcde", topic = "test") + static class WrongRocketMQListener { + + public String onMessage(String message) { + return "test"; + } + } + + @RocketMQMessageListener(nameServer = "127.0.1.1:9876", consumerGroup = "abcd1", topic = "test") + static class TestCustomNameServerRocketMQReplyListener implements RocketMQReplyListener { + + @Override + public String onMessage(String message) { + return "test"; + } + } + @Configuration static class TestTransactionListenerConfig { @Bean diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java index a6cc91db..da6d7775 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java @@ -21,6 +21,7 @@ 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.common.message.MessageExt; import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration; import org.junit.Test; @@ -28,10 +29,13 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessagingException; +import org.springframework.messaging.support.MessageBuilder; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(properties = { @@ -48,6 +52,12 @@ public class RocketMQTemplateTest { @Value("${test.rocketmq.topic}") String topic; + @Value("stringRequestTopic:tagA") + String stringRequestTopic; + + @Value("objectRequestTopic:tagA") + String objectRequestTopic; + @Test public void testSendMessage() { try { @@ -77,6 +87,104 @@ public void testSendMessage() { } } + @Test + public void testSendAndReceive_NullMessage() { + try { + String response = rocketMQTemplate.sendAndReceive(stringRequestTopic, new Message() { + @Override public String getPayload() { + return null; + } + + @Override public MessageHeaders getHeaders() { + return null; + } + }, String.class); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessageContaining("`message` and `message.payload` cannot be null"); + } + + try { + String response = rocketMQTemplate.sendAndReceive(stringRequestTopic, (Object) null, String.class); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessageContaining("Payload must not be null"); + } + } + + @Test + public void testSendAndReceive_Sync() throws InterruptedException { + try { + String responseMessage = rocketMQTemplate.sendAndReceive(stringRequestTopic, MessageBuilder.withPayload("requestTopicSync").build(), String.class); + assertThat(responseMessage).isNotNull(); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); + } + + try { + String responseMessage = rocketMQTemplate.sendAndReceive(stringRequestTopic, "requestTopicSync", String.class, "orderId"); + assertThat(responseMessage).isNotNull(); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); + } + } + + @Test + public void testSendAndReceive_Async() { + try { + rocketMQTemplate.sendAndReceive(stringRequestTopic, MessageBuilder.withPayload("requestTopicASync").build(), new RocketMQLocalRequestCallback() { + @Override public void onSuccess(String message) { + System.out.printf("receive string: %s %n", message); + } + + @Override public void onException(Throwable e) { + e.printStackTrace(); + } + }); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); + } + + try { + rocketMQTemplate.sendAndReceive(stringRequestTopic, "requestTopicAsyncWithHasKey", new RocketMQLocalRequestCallback() { + @Override public void onSuccess(String message) { + System.out.printf("receive string: %s %n", message); + } + + @Override public void onException(Throwable e) { + e.printStackTrace(); + } + }, "order-id"); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); + } + + try { + rocketMQTemplate.sendAndReceive(stringRequestTopic, "requestTopicAsyncWithTimeout", new RocketMQLocalRequestCallback() { + @Override public void onSuccess(String message) { + System.out.printf("receive string: %s %n", message); + } + + @Override public void onException(Throwable e) { + e.printStackTrace(); + } + }, "order-id", 5000); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); + } + try { + rocketMQTemplate.sendAndReceive(objectRequestTopic, "requestTopicAsyncWithTimeout", new RocketMQLocalRequestCallback() { + @Override public void onSuccess(MessageExt message) { + System.out.printf("receive messageExt: %s %n", message.toString()); + } + + @Override public void onException(Throwable e) { + e.printStackTrace(); + } + }, 5000); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); + } + } + @Test public void testProperties() { assertThat(rocketMQTemplate.getProducer().getNamesrvAddr()).isEqualTo("127.0.0.1:9876"); 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 60014c9e..7133b982 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 @@ -16,12 +16,16 @@ */ package org.apache.rocketmq.spring.support; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.remoting.protocol.RemotingSerializable; import org.apache.rocketmq.spring.core.RocketMQListener; +import org.apache.rocketmq.spring.core.RocketMQReplyListener; import org.junit.Test; import org.springframework.core.MethodParameter; +import org.springframework.messaging.Message; import org.springframework.messaging.converter.CompositeMessageConverter; import org.springframework.messaging.converter.MappingJackson2MessageConverter; import org.springframework.messaging.converter.StringMessageConverter; @@ -29,6 +33,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import org.springframework.messaging.support.MessageBuilder; import static org.assertj.core.api.Assertions.assertThat; @@ -54,6 +59,64 @@ public void onMessage(MessageExt message) { }); result = (Class) getMessageType.invoke(listenerContainer); assertThat(result.getName().equals(MessageExt.class.getName())); + + listenerContainer.setRocketMQReplyListener(new RocketMQReplyListener() { + @Override + public String onMessage(MessageExt message) { + return "test"; + } + }); + result = (Class) getMessageType.invoke(listenerContainer); + assertThat(result.getName().equals(MessageExt.class.getName())); + + listenerContainer.setRocketMQReplyListener(new RocketMQReplyListener() { + @Override + public String onMessage(String message) { + return "test"; + } + }); + result = (Class) getMessageType.invoke(listenerContainer); + assertThat(result.getName().equals(String.class.getName())); + } + + @Test + public void testDoConvertMessage() throws Exception { + DefaultRocketMQListenerContainer listenerContainer = new DefaultRocketMQListenerContainer(); + Method doConvertMessage = DefaultRocketMQListenerContainer.class.getDeclaredMethod("doConvertMessage", MessageExt.class); + doConvertMessage.setAccessible(true); + + listenerContainer.setRocketMQListener(new RocketMQListener() { + @Override + public void onMessage(String message) { + } + }); + + Field messageType = DefaultRocketMQListenerContainer.class.getDeclaredField("messageType"); + messageType.setAccessible(true); + messageType.set(listenerContainer, String.class); + MessageExt messageExt = new MessageExt(0, System.currentTimeMillis(), null, System.currentTimeMillis(), null, null); + messageExt.setBody("hello".getBytes()); + String result = (String) doConvertMessage.invoke(listenerContainer, messageExt); + assertThat(result).isEqualTo("hello"); + + listenerContainer.setRocketMQListener(new RocketMQListener() { + @Override + public void onMessage(MessageExt message) { + } + }); + Field messageType2 = DefaultRocketMQListenerContainer.class.getDeclaredField("messageType"); + messageType2.setAccessible(true); + messageType2.set(listenerContainer, MessageExt.class); + messageExt = new MessageExt(0, System.currentTimeMillis(), null, System.currentTimeMillis(), null, null); + messageExt.setBody("hello".getBytes()); + MessageExt result2 = (MessageExt) doConvertMessage.invoke(listenerContainer, messageExt); + assertThat(result2).isEqualTo(messageExt); + + listenerContainer.setRocketMQListener(new RocketMQListener() { + @Override + public void onMessage(User message) { + } + }); } @Test @@ -76,6 +139,41 @@ public void onMessage(ArrayList message) { assertThat(type.getRawType() == ArrayList.class); MethodParameter methodParameter = ((MethodParameter) getMethodParameter.invoke(listenerContainer)); assertThat(methodParameter.getParameterType() == ArrayList.class); + + listenerContainer.setRocketMQReplyListener(new RocketMQReplyListener, String>() { + @Override + public String onMessage(ArrayList message) { + return "test"; + } + }); + + type = (ParameterizedType) getMessageType.invoke(listenerContainer); + assertThat(type.getRawType() == ArrayList.class); + methodParameter = ((MethodParameter) getMethodParameter.invoke(listenerContainer)); + assertThat(methodParameter.getParameterType() == ArrayList.class); + } + + class User { + private String userName; + private int userAge; + + public String getUserName() { + return userName; + } + + public User setUserName(String userName) { + this.userName = userName; + return this; + } + + public int getUserAge() { + return userAge; + } + + public User setUserAge(int userAge) { + this.userAge = userAge; + return this; + } } } From c7f230f98a5285efed9456c64ad2d02974a0e2dd Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Wed, 5 Feb 2020 10:45:57 +0800 Subject: [PATCH 061/105] doc(notice):update notice's year to 2020 --- NOTICE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE b/NOTICE index 85e2dc3f..65ebdd03 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache RocketMQ -Copyright 2016-2019 The Apache Software Foundation +Copyright 2016-2020 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). From 2853384030397fe9453316c05b68b6d570d67019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=88=B1=E5=9B=A0=E6=96=AF=E5=94=90?= Date: Mon, 10 Feb 2020 14:49:33 +0800 Subject: [PATCH 062/105] [ISSUE #218] Fix spring scopeTarget will repeat consumer instance (#210) * change clientId algorithm * code format * develop * optimize on 2.0.5.EINSITANG * revert pom version * change note * change note * revert demo.rocketmq.myNameServer * remove clientInstaceName * remove unuse method * pass ci-check * remove pass annotation * correct variable word * optimize annotation * merge Co-authored-by: von gosling --- .../ExtProducerResetConfiguration.java | 13 ++--- .../ListenerContainerConfiguration.java | 21 +++++--- .../RocketMQTransactionConfiguration.java | 10 ++-- .../spring/support/SpringBeanUtil.java | 52 +++++++++++++++++++ 4 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/SpringBeanUtil.java diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index e5e74336..9ea7699b 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -25,6 +25,7 @@ import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.apache.rocketmq.spring.support.RocketMQUtil; +import org.apache.rocketmq.spring.support.SpringBeanUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; @@ -52,7 +53,7 @@ public class ExtProducerResetConfiguration implements ApplicationContextAware, S private RocketMQMessageConverter rocketMQMessageConverter; public ExtProducerResetConfiguration(RocketMQMessageConverter rocketMQMessageConverter, - StandardEnvironment environment, RocketMQProperties rocketMQProperties) { + StandardEnvironment environment, RocketMQProperties rocketMQProperties) { this.rocketMQMessageConverter = rocketMQMessageConverter; this.environment = environment; this.rocketMQProperties = rocketMQProperties; @@ -60,12 +61,12 @@ public ExtProducerResetConfiguration(RocketMQMessageConverter rocketMQMessageCon @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = (ConfigurableApplicationContext)applicationContext; + this.applicationContext = (ConfigurableApplicationContext) applicationContext; } @Override public void afterSingletonsInstantiated() { - Map beans = this.applicationContext.getBeansWithAnnotation(ExtRocketMQTemplateConfiguration.class); + Map beans = SpringBeanUtil.getBeansWithAnnotation(this.applicationContext, ExtRocketMQTemplateConfiguration.class); if (Objects.nonNull(beans)) { beans.forEach(this::registerTemplate); @@ -80,7 +81,7 @@ private void registerTemplate(String beanName, Object bean) { } ExtRocketMQTemplateConfiguration annotation = clazz.getAnnotation(ExtRocketMQTemplateConfiguration.class); - GenericApplicationContext genericApplicationContext = (GenericApplicationContext)applicationContext; + GenericApplicationContext genericApplicationContext = (GenericApplicationContext) applicationContext; validate(annotation, genericApplicationContext); DefaultMQProducer mqProducer = createProducer(annotation); @@ -92,7 +93,7 @@ private void registerTemplate(String beanName, Object bean) { throw new BeanDefinitionValidationException(String.format("Failed to startup MQProducer for RocketMQTemplate {}", beanName), e); } - RocketMQTemplate rocketMQTemplate = (RocketMQTemplate)bean; + RocketMQTemplate rocketMQTemplate = (RocketMQTemplate) bean; rocketMQTemplate.setProducer(mqProducer); rocketMQTemplate.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); log.info("Set real producer to :{} {}", beanName, annotation.value()); @@ -130,7 +131,7 @@ private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annota } private void validate(ExtRocketMQTemplateConfiguration annotation, - GenericApplicationContext genericApplicationContext) { + GenericApplicationContext genericApplicationContext) { if (genericApplicationContext.isBeanNameInUse(annotation.value())) { throw new BeanDefinitionValidationException(String.format("Bean {} has been used in Spring Application Context, " + "please check the @ExtRocketMQTemplateConfiguration", diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index 699474de..008a4dbe 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -17,10 +17,6 @@ package org.apache.rocketmq.spring.autoconfigure; -import java.util.Collections; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicLong; import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.spring.annotation.ConsumeMode; import org.apache.rocketmq.spring.annotation.MessageModel; @@ -29,6 +25,7 @@ import org.apache.rocketmq.spring.core.RocketMQReplyListener; import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; +import org.apache.rocketmq.spring.support.SpringBeanUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; @@ -43,6 +40,11 @@ import org.springframework.core.env.StandardEnvironment; import org.springframework.util.StringUtils; +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicLong; + @Configuration public class ListenerContainerConfiguration implements ApplicationContextAware, SmartInitializingSingleton { private final static Logger log = LoggerFactory.getLogger(ListenerContainerConfiguration.class); @@ -58,7 +60,7 @@ public class ListenerContainerConfiguration implements ApplicationContextAware, private RocketMQMessageConverter rocketMQMessageConverter; public ListenerContainerConfiguration(RocketMQMessageConverter rocketMQMessageConverter, - StandardEnvironment environment, RocketMQProperties rocketMQProperties) { + StandardEnvironment environment, RocketMQProperties rocketMQProperties) { this.rocketMQMessageConverter = rocketMQMessageConverter; this.environment = environment; this.rocketMQProperties = rocketMQProperties; @@ -71,7 +73,8 @@ public void setApplicationContext(ApplicationContext applicationContext) throws @Override public void afterSingletonsInstantiated() { - Map beans = this.applicationContext.getBeansWithAnnotation(RocketMQMessageListener.class); + Map beans = SpringBeanUtil.getBeansWithAnnotation(this.applicationContext, RocketMQMessageListener. + class); if (Objects.nonNull(beans)) { beans.forEach(this::registerContainer); @@ -127,7 +130,7 @@ private void registerContainer(String beanName, Object bean) { } private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String name, Object bean, - RocketMQMessageListener annotation) { + RocketMQMessageListener annotation) { DefaultRocketMQListenerContainer container = new DefaultRocketMQListenerContainer(); container.setRocketMQMessageListener(annotation); @@ -145,13 +148,15 @@ private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String container.setSelectorExpression(tags); } container.setConsumerGroup(environment.resolvePlaceholders(annotation.consumerGroup())); + if (RocketMQListener.class.isAssignableFrom(bean.getClass())) { container.setRocketMQListener((RocketMQListener) bean); } else if (RocketMQReplyListener.class.isAssignableFrom(bean.getClass())) { container.setRocketMQReplyListener((RocketMQReplyListener) bean); } + container.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); - container.setName(name); // REVIEW ME, use the same clientId or multiple? + container.setName(name); return container; } diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.java index 1a897e51..2daefcfc 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.java @@ -22,11 +22,13 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; + import org.apache.rocketmq.client.producer.TransactionMQProducer; import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQUtil; +import org.apache.rocketmq.spring.support.SpringBeanUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; @@ -44,12 +46,14 @@ public class RocketMQTransactionConfiguration implements ApplicationContextAware private ConfigurableApplicationContext applicationContext; - @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = (ConfigurableApplicationContext) applicationContext; } - @Override public void afterSingletonsInstantiated() { - Map beans = this.applicationContext.getBeansWithAnnotation(RocketMQTransactionListener.class); + @Override + public void afterSingletonsInstantiated() { + Map beans = SpringBeanUtil.getBeansWithAnnotation(this.applicationContext, RocketMQTransactionListener.class); if (Objects.nonNull(beans)) { beans.forEach(this::registerTransactionListener); diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/SpringBeanUtil.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/SpringBeanUtil.java new file mode 100644 index 00000000..b5d11615 --- /dev/null +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/SpringBeanUtil.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.support; + +import org.springframework.aop.scope.ScopedProxyUtils; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.lang.NonNull; + +import java.lang.annotation.Annotation; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class SpringBeanUtil { + + /** + * Override applicationContext.getBeansWithAnnotation method to make sure without same ProxyTarget beans + * + * @param applicationContext spring Application Context + * @param clazz annotation class + * @return beans map without proxyTarget bean + */ + public static Map getBeansWithAnnotation(@NonNull ConfigurableApplicationContext applicationContext, Class clazz) { + Map beans = applicationContext.getBeansWithAnnotation(clazz); + Map filterBeans = new HashMap<>(beans.size()); + // remove proxy target + Set> entrySet = beans.entrySet(); + entrySet.forEach((entry) -> { + final String beanName = entry.getKey(); + if (!ScopedProxyUtils.isScopedTarget(beanName)) { + filterBeans.put(beanName, entry.getValue()); + } + }); + return filterBeans; + } + +} From 82f3e581926412175cc8570057cf931659581baa Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Mon, 10 Feb 2020 15:32:21 +0800 Subject: [PATCH 063/105] chore(autoconfigure):polish the pr #210 --- .../ExtProducerResetConfiguration.java | 16 +++--- .../ListenerContainerConfiguration.java | 26 ++++------ .../RocketMQTransactionConfiguration.java | 19 +++---- .../spring/support/SpringBeanUtil.java | 52 ------------------- 4 files changed, 27 insertions(+), 86 deletions(-) delete mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/SpringBeanUtil.java diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index 9ea7699b..a0cc706c 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -18,17 +18,17 @@ package org.apache.rocketmq.spring.autoconfigure; import java.util.Map; -import java.util.Objects; +import java.util.stream.Collectors; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.apache.rocketmq.spring.support.RocketMQUtil; -import org.apache.rocketmq.spring.support.SpringBeanUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; +import org.springframework.aop.scope.ScopedProxyUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.support.BeanDefinitionValidationException; @@ -53,7 +53,7 @@ public class ExtProducerResetConfiguration implements ApplicationContextAware, S private RocketMQMessageConverter rocketMQMessageConverter; public ExtProducerResetConfiguration(RocketMQMessageConverter rocketMQMessageConverter, - StandardEnvironment environment, RocketMQProperties rocketMQProperties) { + StandardEnvironment environment, RocketMQProperties rocketMQProperties) { this.rocketMQMessageConverter = rocketMQMessageConverter; this.environment = environment; this.rocketMQProperties = rocketMQProperties; @@ -66,11 +66,11 @@ public void setApplicationContext(ApplicationContext applicationContext) throws @Override public void afterSingletonsInstantiated() { - Map beans = SpringBeanUtil.getBeansWithAnnotation(this.applicationContext, ExtRocketMQTemplateConfiguration.class); + Map beans = this.applicationContext.getBeansWithAnnotation(ExtRocketMQTemplateConfiguration.class) + .entrySet().stream().filter(entry -> !ScopedProxyUtils.isScopedTarget(entry.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - if (Objects.nonNull(beans)) { - beans.forEach(this::registerTemplate); - } + beans.forEach(this::registerTemplate); } private void registerTemplate(String beanName, Object bean) { @@ -131,7 +131,7 @@ private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annota } private void validate(ExtRocketMQTemplateConfiguration annotation, - GenericApplicationContext genericApplicationContext) { + GenericApplicationContext genericApplicationContext) { if (genericApplicationContext.isBeanNameInUse(annotation.value())) { throw new BeanDefinitionValidationException(String.format("Bean {} has been used in Spring Application Context, " + "please check the @ExtRocketMQTemplateConfiguration", diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java index 008a4dbe..1e3f1eda 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -17,6 +17,10 @@ package org.apache.rocketmq.spring.autoconfigure; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.spring.annotation.ConsumeMode; import org.apache.rocketmq.spring.annotation.MessageModel; @@ -25,10 +29,10 @@ import org.apache.rocketmq.spring.core.RocketMQReplyListener; import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; -import org.apache.rocketmq.spring.support.SpringBeanUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; +import org.springframework.aop.scope.ScopedProxyUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.support.BeanDefinitionValidationException; @@ -40,11 +44,6 @@ import org.springframework.core.env.StandardEnvironment; import org.springframework.util.StringUtils; -import java.util.Collections; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicLong; - @Configuration public class ListenerContainerConfiguration implements ApplicationContextAware, SmartInitializingSingleton { private final static Logger log = LoggerFactory.getLogger(ListenerContainerConfiguration.class); @@ -60,7 +59,7 @@ public class ListenerContainerConfiguration implements ApplicationContextAware, private RocketMQMessageConverter rocketMQMessageConverter; public ListenerContainerConfiguration(RocketMQMessageConverter rocketMQMessageConverter, - StandardEnvironment environment, RocketMQProperties rocketMQProperties) { + StandardEnvironment environment, RocketMQProperties rocketMQProperties) { this.rocketMQMessageConverter = rocketMQMessageConverter; this.environment = environment; this.rocketMQProperties = rocketMQProperties; @@ -73,12 +72,11 @@ public void setApplicationContext(ApplicationContext applicationContext) throws @Override public void afterSingletonsInstantiated() { - Map beans = SpringBeanUtil.getBeansWithAnnotation(this.applicationContext, RocketMQMessageListener. - class); + Map beans = this.applicationContext.getBeansWithAnnotation(RocketMQMessageListener.class) + .entrySet().stream().filter(entry -> !ScopedProxyUtils.isScopedTarget(entry.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - if (Objects.nonNull(beans)) { - beans.forEach(this::registerContainer); - } + beans.forEach(this::registerContainer); } private void registerContainer(String beanName, Object bean) { @@ -130,7 +128,7 @@ private void registerContainer(String beanName, Object bean) { } private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String name, Object bean, - RocketMQMessageListener annotation) { + RocketMQMessageListener annotation) { DefaultRocketMQListenerContainer container = new DefaultRocketMQListenerContainer(); container.setRocketMQMessageListener(annotation); @@ -148,13 +146,11 @@ private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String container.setSelectorExpression(tags); } container.setConsumerGroup(environment.resolvePlaceholders(annotation.consumerGroup())); - if (RocketMQListener.class.isAssignableFrom(bean.getClass())) { container.setRocketMQListener((RocketMQListener) bean); } else if (RocketMQReplyListener.class.isAssignableFrom(bean.getClass())) { container.setRocketMQReplyListener((RocketMQReplyListener) bean); } - container.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); container.setName(name); diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.java index 2daefcfc..74badbb6 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQTransactionConfiguration.java @@ -18,20 +18,19 @@ package org.apache.rocketmq.spring.autoconfigure; import java.util.Map; -import java.util.Objects; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; - +import java.util.stream.Collectors; import org.apache.rocketmq.client.producer.TransactionMQProducer; import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQUtil; -import org.apache.rocketmq.spring.support.SpringBeanUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; +import org.springframework.aop.scope.ScopedProxyUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.context.ApplicationContext; @@ -46,18 +45,16 @@ public class RocketMQTransactionConfiguration implements ApplicationContextAware private ConfigurableApplicationContext applicationContext; - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = (ConfigurableApplicationContext) applicationContext; } - @Override - public void afterSingletonsInstantiated() { - Map beans = SpringBeanUtil.getBeansWithAnnotation(this.applicationContext, RocketMQTransactionListener.class); + @Override public void afterSingletonsInstantiated() { + Map beans = this.applicationContext.getBeansWithAnnotation(RocketMQTransactionListener.class) + .entrySet().stream().filter(entry -> !ScopedProxyUtils.isScopedTarget(entry.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - if (Objects.nonNull(beans)) { - beans.forEach(this::registerTransactionListener); - } + beans.forEach(this::registerTransactionListener); } private void registerTransactionListener(String beanName, Object bean) { diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/SpringBeanUtil.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/SpringBeanUtil.java deleted file mode 100644 index b5d11615..00000000 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/SpringBeanUtil.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.springframework.aop.scope.ScopedProxyUtils; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.lang.NonNull; - -import java.lang.annotation.Annotation; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public class SpringBeanUtil { - - /** - * Override applicationContext.getBeansWithAnnotation method to make sure without same ProxyTarget beans - * - * @param applicationContext spring Application Context - * @param clazz annotation class - * @return beans map without proxyTarget bean - */ - public static Map getBeansWithAnnotation(@NonNull ConfigurableApplicationContext applicationContext, Class clazz) { - Map beans = applicationContext.getBeansWithAnnotation(clazz); - Map filterBeans = new HashMap<>(beans.size()); - // remove proxy target - Set> entrySet = beans.entrySet(); - entrySet.forEach((entry) -> { - final String beanName = entry.getKey(); - if (!ScopedProxyUtils.isScopedTarget(beanName)) { - filterBeans.put(beanName, entry.getValue()); - } - }); - return filterBeans; - } - -} From 6c8fc6ef596f114dfbaf6bddddbcc077eefb73b7 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Wed, 12 Feb 2020 15:31:04 +0800 Subject: [PATCH 064/105] [maven-release-plugin] prepare release rocketmq-spring-all-2.1.0 --- pom.xml | 4 ++-- rocketmq-spring-boot-parent/pom.xml | 4 ++-- rocketmq-spring-boot-starter/pom.xml | 2 +- rocketmq-spring-boot/pom.xml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 827ae1a7..6e9e32d1 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.1.0-SNAPSHOT + 2.1.0 pom Apache RocketMQ Spring Boot ${project.version} @@ -39,7 +39,7 @@ git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git - HEAD + rocketmq-spring-all-2.1.0 diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index bf62ce49..ac429afc 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.1.0-SNAPSHOT + 2.1.0 ../pom.xml @@ -38,7 +38,7 @@ 2.0.5.RELEASE 5.1.0.RELEASE - 2.1.0-SNAPSHOT + 2.1.0 4.6.0 1.7.25 diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml index 71ea5cda..0cdf1670 100644 --- a/rocketmq-spring-boot-starter/pom.xml +++ b/rocketmq-spring-boot-starter/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.1.0-SNAPSHOT + 2.1.0 ../rocketmq-spring-boot-parent/pom.xml diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml index cd1d2a40..2f04fd5d 100644 --- a/rocketmq-spring-boot/pom.xml +++ b/rocketmq-spring-boot/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.1.0-SNAPSHOT + 2.1.0 ../rocketmq-spring-boot-parent/pom.xml From 287f3ed97e28c533900158c8fee6b04702fc7ee8 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Wed, 12 Feb 2020 15:38:21 +0800 Subject: [PATCH 065/105] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- rocketmq-spring-boot-parent/pom.xml | 4 ++-- rocketmq-spring-boot-starter/pom.xml | 2 +- rocketmq-spring-boot/pom.xml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 6e9e32d1..9b706227 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.1.0 + 2.1.1-SNAPSHOT pom Apache RocketMQ Spring Boot ${project.version} @@ -39,7 +39,7 @@ git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git - rocketmq-spring-all-2.1.0 + HEAD diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index ac429afc..1b0130a8 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.1.0 + 2.1.1-SNAPSHOT ../pom.xml @@ -38,7 +38,7 @@ 2.0.5.RELEASE 5.1.0.RELEASE - 2.1.0 + 2.1.1-SNAPSHOT 4.6.0 1.7.25 diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml index 0cdf1670..b221f96b 100644 --- a/rocketmq-spring-boot-starter/pom.xml +++ b/rocketmq-spring-boot-starter/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.1.0 + 2.1.1-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml index 2f04fd5d..0c22dd7a 100644 --- a/rocketmq-spring-boot/pom.xml +++ b/rocketmq-spring-boot/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.1.0 + 2.1.1-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml From 3fb0596cae353b939aa8bcc2b2ed736a825dde15 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Wed, 19 Feb 2020 22:44:15 +0800 Subject: [PATCH 066/105] chore(all):add asf license to properties file and update readme and version of samples --- README.md | 2 +- rocketmq-spring-boot-samples/pom.xml | 4 ++-- .../rocketmq-consume-acl-demo/pom.xml | 2 +- .../src/main/resources/application.properties | 16 ++++++++++++++++ .../rocketmq-consume-demo/pom.xml | 2 +- .../src/main/resources/application.properties | 15 +++++++++++++++ .../rocketmq-produce-acl-demo/pom.xml | 2 +- .../src/main/resources/application.properties | 15 +++++++++++++++ .../rocketmq-produce-demo/pom.xml | 2 +- .../src/main/resources/application.properties | 15 +++++++++++++++ 10 files changed, 68 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index dfb8d0b8..7d0629d2 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ This project aims to help developers quickly integrate [RocketMQ](http://rocketm - [x] Filter messages using the tag or sql92 expression - [x] Suport message tracing - [x] Support authentication and authorization -- [ ] Support request-reply message exchange pattern +- [x] Support request-reply message exchange pattern ## Prerequisites - JDK 1.8 and above diff --git a/rocketmq-spring-boot-samples/pom.xml b/rocketmq-spring-boot-samples/pom.xml index 1787afdd..ca74d548 100644 --- a/rocketmq-spring-boot-samples/pom.xml +++ b/rocketmq-spring-boot-samples/pom.xml @@ -24,7 +24,7 @@ org.apache.rocketmq rocketmq-spring-boot-samples pom - 0.0.1-SNAPSHOT + 2.1.1-SNAPSHOT RocketMQ Spring Boot Samples Samples for RocketMQ Spring Boot @@ -38,7 +38,7 @@ - 2.1.0-SNAPSHOT + 2.1.0 diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml index 47fc2212..07117783 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml +++ b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml @@ -23,7 +23,7 @@ org.apache.rocketmq rocketmq-spring-boot-samples - 0.0.1-SNAPSHOT + 2.1.1-SNAPSHOT rocketmq-consume-acl-demo diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/resources/application.properties b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/resources/application.properties index 7ca3c429..057edebc 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/resources/application.properties +++ b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/resources/application.properties @@ -1,3 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + spring.application.name=rocketmq-consume-acl-demo rocketmq.name-server=Endpoint_of_Aliware_MQ diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml b/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml index 4093170b..a63328af 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml @@ -23,7 +23,7 @@ org.apache.rocketmq rocketmq-spring-boot-samples - 0.0.1-SNAPSHOT + 2.1.1-SNAPSHOT rocketmq-consume-demo 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 5be0358d..096cbb50 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,3 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + spring.application.name=rocketmq-consume-demo rocketmq.name-server=localhost:9876 diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml b/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml index 9193d986..4bc87c3a 100644 --- a/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml +++ b/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml @@ -23,7 +23,7 @@ org.apache.rocketmq rocketmq-spring-boot-samples - 0.0.1-SNAPSHOT + 2.1.1-SNAPSHOT rocketmq-produce-acl-demo diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/resources/application.properties b/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/resources/application.properties index dd49d0dc..08722805 100644 --- a/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/resources/application.properties +++ b/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/resources/application.properties @@ -1,3 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + rocketmq.name-server=Endpoint_of_Aliware_MQ rocketmq.producer.group=my-group1 rocketmq.producer.access-key=AK diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml b/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml index 0ef364d1..05de2f8f 100644 --- a/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml +++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml @@ -23,7 +23,7 @@ org.apache.rocketmq rocketmq-spring-boot-samples - 0.0.1-SNAPSHOT + 2.1.1-SNAPSHOT rocketmq-produce-demo 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 c68ac3a0..7b5e4228 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,3 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + rocketmq.name-server=localhost:9876 rocketmq.producer.group=my-group1 rocketmq.producer.sendMessageTimeout=300000 From 8e6f11c2c0db8f3ff22e34e13130637f7343e686 Mon Sep 17 00:00:00 2001 From: rongtongjin <794220751@qq.com> Date: Fri, 21 Feb 2020 12:17:04 +0800 Subject: [PATCH 067/105] docs(readme):typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d0629d2..cb593dc3 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ This project aims to help developers quickly integrate [RocketMQ](http://rocketm - [x] Consume messages with concurrently mode (broadcasting/clustering) - [x] Consume ordered messages - [x] Filter messages using the tag or sql92 expression -- [x] Suport message tracing +- [x] Support message tracing - [x] Support authentication and authorization - [x] Support request-reply message exchange pattern From 7d93931b110a707ac4bfb0d34f6bb078598f8dbc Mon Sep 17 00:00:00 2001 From: GongZhengMe <790707059@qq.com> Date: Thu, 26 Mar 2020 15:08:13 +0800 Subject: [PATCH 068/105] Add Method:#syncSend(java.lang.String, java.util.Collection) Fix the bug of BatchMessage syncSend without timeout --- .../spring/core/RocketMQTemplate.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) 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 089016a9..626b16f8 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 @@ -466,6 +466,42 @@ public SendResult syncSend(String destination, Message message, long timeout) return syncSend(destination, message, timeout, 0); } + /** + * syncSend batch messages + * + * @param destination formats: `topicName:tags` + * @param messages Collection of {@link org.springframework.messaging.Message} + * @return {@link SendResult} + */ + public SendResult syncSend(String destination, Collection messages) { + if (Objects.isNull(messages) || messages.size() == 0) { + log.error("syncSend with batch failed. destination:{}, messages is empty ", destination); + throw new IllegalArgumentException("`messages` can not be empty"); + } + + try { + long now = System.currentTimeMillis(); + Collection rmqMsgs = new ArrayList<>(); + for (Message msg : messages) { + if (Objects.isNull(msg) || Objects.isNull(msg.getPayload())) { + log.warn("Found a message empty in the batch, skip it"); + continue; + } + rmqMsgs.add(this.createRocketMqMessage(destination, msg)); + } + + SendResult sendResult = producer.send(rmqMsgs); + long costTime = System.currentTimeMillis() - now; + if (log.isDebugEnabled()) { + log.debug("send messages cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); + } + return sendResult; + } catch (Exception e) { + log.error("syncSend with batch failed. destination:{}, messages.size:{} ", destination, messages.size()); + throw new MessagingException(e.getMessage(), e); + } + } + /** * syncSend batch messages in a given timeout. * From 0927fe80107c8019b8c532d254079ec6579698d0 Mon Sep 17 00:00:00 2001 From: GongZhengMe <790707059@qq.com> Date: Thu, 26 Mar 2020 21:05:13 +0800 Subject: [PATCH 069/105] Add Method:#syncSend(java.lang.String, java.util.Collection) Fix the bug of BatchMessage syncSend without timeout --- .../spring/core/RocketMQTemplate.java | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) 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 626b16f8..70001f0c 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 @@ -474,32 +474,7 @@ public SendResult syncSend(String destination, Message message, long timeout) * @return {@link SendResult} */ public SendResult syncSend(String destination, Collection messages) { - if (Objects.isNull(messages) || messages.size() == 0) { - log.error("syncSend with batch failed. destination:{}, messages is empty ", destination); - throw new IllegalArgumentException("`messages` can not be empty"); - } - - try { - long now = System.currentTimeMillis(); - Collection rmqMsgs = new ArrayList<>(); - for (Message msg : messages) { - if (Objects.isNull(msg) || Objects.isNull(msg.getPayload())) { - log.warn("Found a message empty in the batch, skip it"); - continue; - } - rmqMsgs.add(this.createRocketMqMessage(destination, msg)); - } - - SendResult sendResult = producer.send(rmqMsgs); - long costTime = System.currentTimeMillis() - now; - if (log.isDebugEnabled()) { - log.debug("send messages cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); - } - return sendResult; - } catch (Exception e) { - log.error("syncSend with batch failed. destination:{}, messages.size:{} ", destination, messages.size()); - throw new MessagingException(e.getMessage(), e); - } + return syncSend(destination,messages,producer.getSendMsgTimeout()); } /** From fefe366b441464459519d09c0c493daebec3b9be Mon Sep 17 00:00:00 2001 From: GongZhengMe <790707059@qq.com> Date: Thu, 26 Mar 2020 22:51:37 +0800 Subject: [PATCH 070/105] Fix code style error due to mvn build failed --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 9b706227..8c48c829 100644 --- a/pom.xml +++ b/pom.xml @@ -89,6 +89,7 @@ validate validate + true src/main/resources style/rmq_checkstyle.xml UTF-8 From 4432a7be02d428abb9012fc55172e7f3ee4220bf Mon Sep 17 00:00:00 2001 From: GongZhengMe <790707059@qq.com> Date: Fri, 27 Mar 2020 12:40:15 +0800 Subject: [PATCH 071/105] Edit code style as Apache Rocket MQ --- .../spring/core/RocketMQTemplate.java | 349 +++++++++--------- 1 file changed, 183 insertions(+), 166 deletions(-) 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 70001f0c..1ac4e783 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 @@ -88,8 +88,8 @@ public void setMessageQueueSelector(MessageQueueSelector messageQueueSelector) { /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type of T + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T * @return */ public T sendAndReceive(String destination, Message message, Type type) { @@ -98,8 +98,8 @@ public T sendAndReceive(String destination, Message message, Type type) { /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type of T + * @param payload the payload to be sent. + * @param type The type of T * @return */ public T sendAndReceive(String destination, Object payload, Type type) { @@ -108,9 +108,9 @@ public T sendAndReceive(String destination, Object payload, Type type) { /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type of T - * @param timeout send timeout in millis + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param timeout send timeout in millis * @return */ public T sendAndReceive(String destination, Message message, Type type, long timeout) { @@ -119,9 +119,9 @@ public T sendAndReceive(String destination, Message message, Type type, l /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type of T - * @param timeout send timeout in millis + * @param payload the payload to be sent. + * @param type The type of T + * @param timeout send timeout in millis * @return */ public T sendAndReceive(String destination, Object payload, Type type, long timeout) { @@ -130,10 +130,10 @@ public T sendAndReceive(String destination, Object payload, Type type, long /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type of T - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public T sendAndReceive(String destination, Message message, Type type, long timeout, int delayLevel) { @@ -142,10 +142,10 @@ public T sendAndReceive(String destination, Message message, Type type, l /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type of T - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param payload the payload to be sent. + * @param type The type of T + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public T sendAndReceive(String destination, Object payload, Type type, long timeout, int delayLevel) { @@ -154,9 +154,9 @@ public T sendAndReceive(String destination, Object payload, Type type, long /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type of T - * @param hashKey needed when sending message orderly + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param hashKey needed when sending message orderly * @return */ public T sendAndReceive(String destination, Message message, Type type, String hashKey) { @@ -165,9 +165,9 @@ public T sendAndReceive(String destination, Message message, Type type, S /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type of T - * @param hashKey needed when sending message orderly + * @param payload the payload to be sent. + * @param type The type of T + * @param hashKey needed when sending message orderly * @return */ public T sendAndReceive(String destination, Object payload, Type type, String hashKey) { @@ -176,10 +176,10 @@ public T sendAndReceive(String destination, Object payload, Type type, Strin /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type of T - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis * @return */ public T sendAndReceive(String destination, Message message, Type type, String hashKey, long timeout) { @@ -188,8 +188,8 @@ public T sendAndReceive(String destination, Message message, Type type, S /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type of T + * @param payload the payload to be sent. + * @param type The type of T * @param hashKey * @return */ @@ -199,11 +199,11 @@ public T sendAndReceive(String destination, Object payload, Type type, Strin /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type that receive - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type that receive + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public T sendAndReceive(String destination, Message message, Type type, String hashKey, @@ -221,12 +221,14 @@ public T sendAndReceive(String destination, Message message, Type type, S MessageExt replyMessage; if (Objects.isNull(hashKey) || hashKey.isEmpty()) { - replyMessage = (MessageExt) producer.request(rocketMsg, timeout); - } else { - replyMessage = (MessageExt) producer.request(rocketMsg, messageQueueSelector, hashKey, timeout); + replyMessage = (MessageExt)producer.request(rocketMsg, timeout); } - return replyMessage != null ? (T) doConvertMessage(replyMessage, type) : null; - } catch (Exception e) { + else { + replyMessage = (MessageExt)producer.request(rocketMsg, messageQueueSelector, hashKey, timeout); + } + return replyMessage != null ? (T)doConvertMessage(replyMessage, type) : null; + } + catch (Exception e) { log.error("send request message failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -234,11 +236,11 @@ public T sendAndReceive(String destination, Message message, Type type, S /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type that receive - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param payload the payload to be sent. + * @param type The type that receive + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public T sendAndReceive(String destination, Object payload, Type type, String hashKey, @@ -248,8 +250,8 @@ public T sendAndReceive(String destination, Object payload, Type type, Strin } /** - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. * @return */ @@ -259,8 +261,8 @@ public void sendAndReceive(String destination, Message message, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. * @return */ @@ -270,10 +272,10 @@ public void sendAndReceive(String destination, Object payload, } /** - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param timeout send timeout in millis + * @param timeout send timeout in millis * @return */ public void sendAndReceive(String destination, Message message, @@ -282,10 +284,10 @@ public void sendAndReceive(String destination, Message message, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param timeout send timeout in millis + * @param timeout send timeout in millis * @return */ public void sendAndReceive(String destination, Object payload, @@ -294,11 +296,11 @@ public void sendAndReceive(String destination, Object payload, } /** - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public void sendAndReceive(String destination, Message message, @@ -307,10 +309,10 @@ public void sendAndReceive(String destination, Message message, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly + * @param hashKey needed when sending message orderly * @return */ public void sendAndReceive(String destination, Object payload, @@ -319,11 +321,11 @@ public void sendAndReceive(String destination, Object payload, } /** - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis * @return */ public void sendAndReceive(String destination, Message message, @@ -332,11 +334,11 @@ public void sendAndReceive(String destination, Message message, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis * @return */ public void sendAndReceive(String destination, Object payload, @@ -345,10 +347,10 @@ public void sendAndReceive(String destination, Object payload, } /** - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly + * @param hashKey needed when sending message orderly * @return */ public void sendAndReceive(String destination, Message message, @@ -357,11 +359,11 @@ public void sendAndReceive(String destination, Message message, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public void sendAndReceive(String destination, Object payload, @@ -370,12 +372,12 @@ public void sendAndReceive(String destination, Object payload, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public void sendAndReceive(String destination, Object payload, @@ -388,12 +390,12 @@ public void sendAndReceive(String destination, Object payload, * Send request message in asynchronous mode.

This method returns immediately. On receiving reply message, * rocketMQLocalRequestCallback will be executed.

* - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public void sendAndReceive(String destination, Message message, @@ -415,7 +417,7 @@ public void sendAndReceive(String destination, Message message, if (rocketMQLocalRequestCallback != null) { requestCallback = new RequestCallback() { @Override public void onSuccess(org.apache.rocketmq.common.message.Message message) { - rocketMQLocalRequestCallback.onSuccess(doConvertMessage((MessageExt) message, getMessageType(rocketMQLocalRequestCallback))); + rocketMQLocalRequestCallback.onSuccess(doConvertMessage((MessageExt)message, getMessageType(rocketMQLocalRequestCallback))); } @Override public void onException(Throwable e) { @@ -425,10 +427,12 @@ public void sendAndReceive(String destination, Message message, } if (Objects.isNull(hashKey) || hashKey.isEmpty()) { producer.request(rocketMsg, requestCallback, timeout); - } else { + } + else { producer.request(rocketMsg, messageQueueSelector, hashKey, requestCallback, timeout); } - } catch ( + } + catch ( Exception e) { log.error("send request message failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); @@ -447,7 +451,7 @@ public void sendAndReceive(String destination, Message message, * duplication issue. * * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} + * @param message {@link org.springframework.messaging.Message} * @return {@link SendResult} */ public SendResult syncSend(String destination, Message message) { @@ -458,8 +462,8 @@ public SendResult syncSend(String destination, Message message) { * 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 message {@link org.springframework.messaging.Message} + * @param timeout send timeout with millis * @return {@link SendResult} */ public SendResult syncSend(String destination, Message message, long timeout) { @@ -470,19 +474,19 @@ public SendResult syncSend(String destination, Message message, long timeout) * syncSend batch messages * * @param destination formats: `topicName:tags` - * @param messages Collection of {@link org.springframework.messaging.Message} + * @param messages Collection of {@link org.springframework.messaging.Message} * @return {@link SendResult} */ public SendResult syncSend(String destination, Collection messages) { - return syncSend(destination,messages,producer.getSendMsgTimeout()); + return syncSend(destination, messages, producer.getSendMsgTimeout()); } /** * syncSend batch messages in a given timeout. * * @param destination formats: `topicName:tags` - * @param messages Collection of {@link org.springframework.messaging.Message} - * @param timeout send timeout with millis + * @param messages Collection of {@link org.springframework.messaging.Message} + * @param timeout send timeout with millis * @return {@link SendResult} */ public SendResult syncSend(String destination, Collection messages, long timeout) { @@ -508,7 +512,8 @@ public SendResult syncSend(String destination, Collection log.debug("send messages cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } catch (Exception e) { + } + catch (Exception e) { log.error("syncSend with batch failed. destination:{}, messages.size:{} ", destination, messages.size()); throw new MessagingException(e.getMessage(), e); } @@ -518,9 +523,9 @@ public SendResult syncSend(String destination, Collection * 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 + * @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) { @@ -540,7 +545,8 @@ public SendResult syncSend(String destination, Message message, long timeout, log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } catch (Exception e) { + } + catch (Exception e) { log.error("syncSend failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -550,7 +556,7 @@ public SendResult syncSend(String destination, Message message, long timeout, * Same to {@link #syncSend(String, Message)}. * * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @param payload the Object to use as payload * @return {@link SendResult} */ public SendResult syncSend(String destination, Object payload) { @@ -561,8 +567,8 @@ public SendResult syncSend(String destination, Object payload) { * 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 + * @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) { @@ -574,8 +580,8 @@ public SendResult syncSend(String destination, Object payload, long 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 ... + * @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) { @@ -586,9 +592,9 @@ public SendResult syncSendOrderly(String destination, Message message, String * 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 + * @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) { @@ -605,7 +611,8 @@ public SendResult syncSendOrderly(String destination, Message message, String log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } catch (Exception e) { + } + catch (Exception e) { log.error("syncSendOrderly failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -615,8 +622,8 @@ public SendResult syncSendOrderly(String destination, Message message, String * 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 ... + * @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) { @@ -627,9 +634,9 @@ public SendResult syncSendOrderly(String destination, Object payload, String has * 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 + * @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) { @@ -641,11 +648,11 @@ public SendResult syncSendOrderly(String destination, Object payload, String has * Same to {@link #asyncSend(String, Message, SendCallback)} with send timeout and delay level specified in * addition. * - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} * @param sendCallback {@link SendCallback} - * @param timeout send timeout with millis - * @param delayLevel level for the delay message + * @param timeout send timeout with millis + * @param delayLevel level for the delay message */ public void asyncSend(String destination, Message message, SendCallback sendCallback, long timeout, int delayLevel) { @@ -659,7 +666,8 @@ public void asyncSend(String destination, Message message, SendCallback sendC rocketMsg.setDelayTimeLevel(delayLevel); } producer.send(rocketMsg, sendCallback, timeout); - } catch (Exception e) { + } + catch (Exception e) { log.info("asyncSend failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -668,10 +676,10 @@ public void asyncSend(String destination, Message message, SendCallback sendC /** * 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 destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} * @param sendCallback {@link SendCallback} - * @param timeout send timeout with millis + * @param timeout send timeout with millis */ public void asyncSend(String destination, Message message, SendCallback sendCallback, long timeout) { asyncSend(destination, message, sendCallback, timeout, 0); @@ -687,8 +695,8 @@ public void asyncSend(String destination, Message message, SendCallback sendC * 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 destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} * @param sendCallback {@link SendCallback} */ public void asyncSend(String destination, Message message, SendCallback sendCallback) { @@ -698,10 +706,10 @@ public void asyncSend(String destination, Message message, SendCallback sendC /** * 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 destination formats: `topicName:tags` + * @param payload the Object to use as payload * @param sendCallback {@link SendCallback} - * @param timeout send timeout with millis + * @param timeout send timeout with millis */ public void asyncSend(String destination, Object payload, SendCallback sendCallback, long timeout) { Message message = MessageBuilder.withPayload(payload).build(); @@ -711,8 +719,8 @@ public void asyncSend(String destination, Object payload, SendCallback sendCallb /** * Same to {@link #asyncSend(String, Message, SendCallback)}. * - * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @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) { @@ -723,11 +731,11 @@ public void asyncSend(String destination, Object payload, SendCallback sendCallb * 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 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 + * @param timeout send timeout with millis */ public void asyncSendOrderly(String destination, Message message, String hashKey, SendCallback sendCallback, long timeout) { @@ -738,7 +746,8 @@ public void asyncSendOrderly(String destination, Message message, String hash try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.send(rocketMsg, messageQueueSelector, hashKey, sendCallback, timeout); - } catch (Exception e) { + } + catch (Exception e) { log.error("asyncSendOrderly failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -747,9 +756,9 @@ public void asyncSendOrderly(String destination, Message message, String hash /** * 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 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) { @@ -759,9 +768,9 @@ public void asyncSendOrderly(String destination, Message message, String hash /** * 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 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) { @@ -771,11 +780,11 @@ public void asyncSendOrderly(String destination, Object payload, String hashKey, /** * 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 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 + * @param timeout send timeout with millis */ public void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback, long timeout) { @@ -790,7 +799,7 @@ public void asyncSendOrderly(String destination, Object payload, String hashKey, * 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} + * @param message {@link org.springframework.messaging.Message} */ public void sendOneWay(String destination, Message message) { if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { @@ -800,7 +809,8 @@ public void sendOneWay(String destination, Message message) { try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.sendOneway(rocketMsg); - } catch (Exception e) { + } + catch (Exception e) { log.error("sendOneWay failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -810,7 +820,7 @@ public void sendOneWay(String destination, Message message) { * Same to {@link #sendOneWay(String, Message)} * * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @param payload the Object to use as payload */ public void sendOneWay(String destination, Object payload) { Message message = MessageBuilder.withPayload(payload).build(); @@ -821,8 +831,8 @@ public void sendOneWay(String destination, Object payload) { * 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 ... + * @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())) { @@ -832,7 +842,8 @@ public void sendOneWayOrderly(String destination, Message message, String has try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.sendOneway(rocketMsg, messageQueueSelector, hashKey); - } catch (Exception e) { + } + catch (Exception e) { log.error("sendOneWayOrderly failed. destination:{}, message:{}", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -842,7 +853,7 @@ public void sendOneWayOrderly(String destination, Message message, String has * Same to {@link #sendOneWayOrderly(String, Message, String)} * * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @param payload the Object to use as payload */ public void sendOneWayOrderly(String destination, Object payload, String hashKey) { Message message = MessageBuilder.withPayload(payload).build(); @@ -883,20 +894,21 @@ public void destroy() { * Send Spring Message in Transaction * * @param destination destination formats: `topicName:tags` - * @param message message {@link org.springframework.messaging.Message} - * @param arg ext arg + * @param message message {@link org.springframework.messaging.Message} + * @param arg ext arg * @return TransactionSendResult * @throws MessagingException */ public TransactionSendResult sendMessageInTransaction(final String destination, final Message message, final Object arg) throws MessagingException { try { - if (((TransactionMQProducer) producer).getTransactionListener() == null) { + if (((TransactionMQProducer)producer).getTransactionListener() == null) { throw new IllegalStateException("The rocketMQTemplate does not exist TransactionListener"); } org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); return producer.sendMessageInTransaction(rocketMsg, arg); - } catch (MQClientException e) { + } + catch (MQClientException e) { throw RocketMQUtil.convert(e); } } @@ -911,24 +923,29 @@ private org.apache.rocketmq.common.message.Message createRocketMqMessage( private Object doConvertMessage(MessageExt messageExt, Type type) { if (Objects.equals(type, MessageExt.class)) { return messageExt; - } else if (Objects.equals(type, byte[].class)) { + } + else if (Objects.equals(type, byte[].class)) { return messageExt.getBody(); - } else { + } + else { String str = new String(messageExt.getBody(), Charset.forName(charset)); if (Objects.equals(type, String.class)) { return str; - } else { + } + else { // If msgType not string, use objectMapper change it. try { if (type instanceof Class) { //if the messageType has not Generic Parameter - return this.getMessageConverter().fromMessage(MessageBuilder.withPayload(str).build(), (Class) type); - } else { + return this.getMessageConverter().fromMessage(MessageBuilder.withPayload(str).build(), (Class)type); + } + else { //if the messageType has Generic Parameter, then use SmartMessageConverter#fromMessage with third parameter "conversionHint". //we have validate the MessageConverter is SmartMessageConverter in this#getMethodParameter. - return ((SmartMessageConverter) this.getMessageConverter()).fromMessage(MessageBuilder.withPayload(str).build(), (Class) ((ParameterizedType) type).getRawType(), null); + return ((SmartMessageConverter)this.getMessageConverter()).fromMessage(MessageBuilder.withPayload(str).build(), (Class)((ParameterizedType)type).getRawType(), null); } - } catch (Exception e) { + } + catch (Exception e) { log.error("convert failed. str:{}, msgType:{}", str, type); throw new RuntimeException("cannot convert message to " + type, e); } @@ -943,7 +960,7 @@ private Type getMessageType(RocketMQLocalRequestCallback rocketMQLocalRequestCal Type[] interfaces = targetClass.getGenericInterfaces(); if (Objects.nonNull(interfaces)) { for (Type type : interfaces) { - if (type instanceof ParameterizedType && (Objects.equals(((ParameterizedType) type).getRawType(), RocketMQLocalRequestCallback.class))) { + if (type instanceof ParameterizedType && (Objects.equals(((ParameterizedType)type).getRawType(), RocketMQLocalRequestCallback.class))) { matchedGenericInterface = type; break; } @@ -955,7 +972,7 @@ private Type getMessageType(RocketMQLocalRequestCallback rocketMQLocalRequestCal return Object.class; } - Type[] actualTypeArguments = ((ParameterizedType) matchedGenericInterface).getActualTypeArguments(); + Type[] actualTypeArguments = ((ParameterizedType)matchedGenericInterface).getActualTypeArguments(); if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) { return actualTypeArguments[0]; } From 4d498cb506c4552df3671b8784a3689119795f6d Mon Sep 17 00:00:00 2001 From: GongZhengMe <790707059@qq.com> Date: Fri, 27 Mar 2020 12:40:31 +0800 Subject: [PATCH 072/105] Edit code style as Apache Rocket MQ --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8c48c829..9b706227 100644 --- a/pom.xml +++ b/pom.xml @@ -89,7 +89,6 @@ validate validate - true src/main/resources style/rmq_checkstyle.xml UTF-8 From 7d50974182952c68fc298ef150274cba38597c03 Mon Sep 17 00:00:00 2001 From: GongZhengMe <790707059@qq.com> Date: Mon, 30 Mar 2020 18:06:04 +0800 Subject: [PATCH 073/105] Edit code style as Apache Rocket MQ --- .../spring/core/RocketMQTemplate.java | 349 +++++++++--------- 1 file changed, 166 insertions(+), 183 deletions(-) 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 1ac4e783..6683f101 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 @@ -88,8 +88,8 @@ public void setMessageQueueSelector(MessageQueueSelector messageQueueSelector) { /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type of T + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T * @return */ public T sendAndReceive(String destination, Message message, Type type) { @@ -98,8 +98,8 @@ public T sendAndReceive(String destination, Message message, Type type) { /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type of T + * @param payload the payload to be sent. + * @param type The type of T * @return */ public T sendAndReceive(String destination, Object payload, Type type) { @@ -108,9 +108,9 @@ public T sendAndReceive(String destination, Object payload, Type type) { /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type of T - * @param timeout send timeout in millis + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param timeout send timeout in millis * @return */ public T sendAndReceive(String destination, Message message, Type type, long timeout) { @@ -119,9 +119,9 @@ public T sendAndReceive(String destination, Message message, Type type, l /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type of T - * @param timeout send timeout in millis + * @param payload the payload to be sent. + * @param type The type of T + * @param timeout send timeout in millis * @return */ public T sendAndReceive(String destination, Object payload, Type type, long timeout) { @@ -130,10 +130,10 @@ public T sendAndReceive(String destination, Object payload, Type type, long /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type of T - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public T sendAndReceive(String destination, Message message, Type type, long timeout, int delayLevel) { @@ -142,10 +142,10 @@ public T sendAndReceive(String destination, Message message, Type type, l /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type of T - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param payload the payload to be sent. + * @param type The type of T + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public T sendAndReceive(String destination, Object payload, Type type, long timeout, int delayLevel) { @@ -154,9 +154,9 @@ public T sendAndReceive(String destination, Object payload, Type type, long /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type of T - * @param hashKey needed when sending message orderly + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param hashKey needed when sending message orderly * @return */ public T sendAndReceive(String destination, Message message, Type type, String hashKey) { @@ -165,9 +165,9 @@ public T sendAndReceive(String destination, Message message, Type type, S /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type of T - * @param hashKey needed when sending message orderly + * @param payload the payload to be sent. + * @param type The type of T + * @param hashKey needed when sending message orderly * @return */ public T sendAndReceive(String destination, Object payload, Type type, String hashKey) { @@ -176,10 +176,10 @@ public T sendAndReceive(String destination, Object payload, Type type, Strin /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type of T - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type of T + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis * @return */ public T sendAndReceive(String destination, Message message, Type type, String hashKey, long timeout) { @@ -188,8 +188,8 @@ public T sendAndReceive(String destination, Message message, Type type, S /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type of T + * @param payload the payload to be sent. + * @param type The type of T * @param hashKey * @return */ @@ -199,11 +199,11 @@ public T sendAndReceive(String destination, Object payload, Type type, Strin /** * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. - * @param type The type that receive - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param type The type that receive + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public T sendAndReceive(String destination, Message message, Type type, String hashKey, @@ -221,14 +221,12 @@ public T sendAndReceive(String destination, Message message, Type type, S MessageExt replyMessage; if (Objects.isNull(hashKey) || hashKey.isEmpty()) { - replyMessage = (MessageExt)producer.request(rocketMsg, timeout); + replyMessage = (MessageExt) producer.request(rocketMsg, timeout); + } else { + replyMessage = (MessageExt) producer.request(rocketMsg, messageQueueSelector, hashKey, timeout); } - else { - replyMessage = (MessageExt)producer.request(rocketMsg, messageQueueSelector, hashKey, timeout); - } - return replyMessage != null ? (T)doConvertMessage(replyMessage, type) : null; - } - catch (Exception e) { + return replyMessage != null ? (T) doConvertMessage(replyMessage, type) : null; + } catch (Exception e) { log.error("send request message failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -236,11 +234,11 @@ public T sendAndReceive(String destination, Message message, Type type, S /** * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. - * @param type The type that receive - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param payload the payload to be sent. + * @param type The type that receive + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public T sendAndReceive(String destination, Object payload, Type type, String hashKey, @@ -250,8 +248,8 @@ public T sendAndReceive(String destination, Object payload, Type type, Strin } /** - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. * @return */ @@ -261,8 +259,8 @@ public void sendAndReceive(String destination, Message message, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. * @return */ @@ -272,10 +270,10 @@ public void sendAndReceive(String destination, Object payload, } /** - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param timeout send timeout in millis + * @param timeout send timeout in millis * @return */ public void sendAndReceive(String destination, Message message, @@ -284,10 +282,10 @@ public void sendAndReceive(String destination, Message message, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param timeout send timeout in millis + * @param timeout send timeout in millis * @return */ public void sendAndReceive(String destination, Object payload, @@ -296,11 +294,11 @@ public void sendAndReceive(String destination, Object payload, } /** - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public void sendAndReceive(String destination, Message message, @@ -309,10 +307,10 @@ public void sendAndReceive(String destination, Message message, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly + * @param hashKey needed when sending message orderly * @return */ public void sendAndReceive(String destination, Object payload, @@ -321,11 +319,11 @@ public void sendAndReceive(String destination, Object payload, } /** - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis * @return */ public void sendAndReceive(String destination, Message message, @@ -334,11 +332,11 @@ public void sendAndReceive(String destination, Message message, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis * @return */ public void sendAndReceive(String destination, Object payload, @@ -347,10 +345,10 @@ public void sendAndReceive(String destination, Object payload, } /** - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly + * @param hashKey needed when sending message orderly * @return */ public void sendAndReceive(String destination, Message message, @@ -359,11 +357,11 @@ public void sendAndReceive(String destination, Message message, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public void sendAndReceive(String destination, Object payload, @@ -372,12 +370,12 @@ public void sendAndReceive(String destination, Object payload, } /** - * @param destination formats: `topicName:tags` - * @param payload the payload to be sent. + * @param destination formats: `topicName:tags` + * @param payload the payload to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public void sendAndReceive(String destination, Object payload, @@ -390,12 +388,12 @@ public void sendAndReceive(String destination, Object payload, * Send request message in asynchronous mode.

This method returns immediately. On receiving reply message, * rocketMQLocalRequestCallback will be executed.

* - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} the message to be sent. + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} the message to be sent. * @param rocketMQLocalRequestCallback callback that will invoked when reply message received. - * @param hashKey needed when sending message orderly - * @param timeout send timeout in millis - * @param delayLevel message delay level(0 means no delay) + * @param hashKey needed when sending message orderly + * @param timeout send timeout in millis + * @param delayLevel message delay level(0 means no delay) * @return */ public void sendAndReceive(String destination, Message message, @@ -417,7 +415,7 @@ public void sendAndReceive(String destination, Message message, if (rocketMQLocalRequestCallback != null) { requestCallback = new RequestCallback() { @Override public void onSuccess(org.apache.rocketmq.common.message.Message message) { - rocketMQLocalRequestCallback.onSuccess(doConvertMessage((MessageExt)message, getMessageType(rocketMQLocalRequestCallback))); + rocketMQLocalRequestCallback.onSuccess(doConvertMessage((MessageExt) message, getMessageType(rocketMQLocalRequestCallback))); } @Override public void onException(Throwable e) { @@ -427,12 +425,10 @@ public void sendAndReceive(String destination, Message message, } if (Objects.isNull(hashKey) || hashKey.isEmpty()) { producer.request(rocketMsg, requestCallback, timeout); - } - else { + } else { producer.request(rocketMsg, messageQueueSelector, hashKey, requestCallback, timeout); } - } - catch ( + } catch ( Exception e) { log.error("send request message failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); @@ -451,7 +447,7 @@ public void sendAndReceive(String destination, Message message, * duplication issue. * * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} + * @param message {@link org.springframework.messaging.Message} * @return {@link SendResult} */ public SendResult syncSend(String destination, Message message) { @@ -462,8 +458,8 @@ public SendResult syncSend(String destination, Message message) { * 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 message {@link org.springframework.messaging.Message} + * @param timeout send timeout with millis * @return {@link SendResult} */ public SendResult syncSend(String destination, Message message, long timeout) { @@ -474,7 +470,7 @@ public SendResult syncSend(String destination, Message message, long timeout) * syncSend batch messages * * @param destination formats: `topicName:tags` - * @param messages Collection of {@link org.springframework.messaging.Message} + * @param messages Collection of {@link org.springframework.messaging.Message} * @return {@link SendResult} */ public SendResult syncSend(String destination, Collection messages) { @@ -485,8 +481,8 @@ public SendResult syncSend(String destination, Collection * syncSend batch messages in a given timeout. * * @param destination formats: `topicName:tags` - * @param messages Collection of {@link org.springframework.messaging.Message} - * @param timeout send timeout with millis + * @param messages Collection of {@link org.springframework.messaging.Message} + * @param timeout send timeout with millis * @return {@link SendResult} */ public SendResult syncSend(String destination, Collection messages, long timeout) { @@ -512,8 +508,7 @@ public SendResult syncSend(String destination, Collection log.debug("send messages cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } - catch (Exception e) { + } catch (Exception e) { log.error("syncSend with batch failed. destination:{}, messages.size:{} ", destination, messages.size()); throw new MessagingException(e.getMessage(), e); } @@ -523,9 +518,9 @@ public SendResult syncSend(String destination, Collection * 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 + * @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) { @@ -545,8 +540,7 @@ public SendResult syncSend(String destination, Message message, long timeout, log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } - catch (Exception e) { + } catch (Exception e) { log.error("syncSend failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -556,7 +550,7 @@ public SendResult syncSend(String destination, Message message, long timeout, * Same to {@link #syncSend(String, Message)}. * * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @param payload the Object to use as payload * @return {@link SendResult} */ public SendResult syncSend(String destination, Object payload) { @@ -567,8 +561,8 @@ public SendResult syncSend(String destination, Object payload) { * 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 + * @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) { @@ -580,8 +574,8 @@ public SendResult syncSend(String destination, Object payload, long 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 ... + * @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) { @@ -592,9 +586,9 @@ public SendResult syncSendOrderly(String destination, Message message, String * 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 + * @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) { @@ -611,8 +605,7 @@ public SendResult syncSendOrderly(String destination, Message message, String log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); } return sendResult; - } - catch (Exception e) { + } catch (Exception e) { log.error("syncSendOrderly failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -622,8 +615,8 @@ public SendResult syncSendOrderly(String destination, Message message, String * 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 ... + * @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) { @@ -634,9 +627,9 @@ public SendResult syncSendOrderly(String destination, Object payload, String has * 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 + * @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) { @@ -648,11 +641,11 @@ public SendResult syncSendOrderly(String destination, Object payload, String has * Same to {@link #asyncSend(String, Message, SendCallback)} with send timeout and delay level specified in * addition. * - * @param destination formats: `topicName:tags` - * @param message {@link org.springframework.messaging.Message} + * @param destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} * @param sendCallback {@link SendCallback} - * @param timeout send timeout with millis - * @param delayLevel level for the delay message + * @param timeout send timeout with millis + * @param delayLevel level for the delay message */ public void asyncSend(String destination, Message message, SendCallback sendCallback, long timeout, int delayLevel) { @@ -666,8 +659,7 @@ public void asyncSend(String destination, Message message, SendCallback sendC rocketMsg.setDelayTimeLevel(delayLevel); } producer.send(rocketMsg, sendCallback, timeout); - } - catch (Exception e) { + } catch (Exception e) { log.info("asyncSend failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -676,10 +668,10 @@ public void asyncSend(String destination, Message message, SendCallback sendC /** * 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 destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} * @param sendCallback {@link SendCallback} - * @param timeout send timeout with millis + * @param timeout send timeout with millis */ public void asyncSend(String destination, Message message, SendCallback sendCallback, long timeout) { asyncSend(destination, message, sendCallback, timeout, 0); @@ -695,8 +687,8 @@ public void asyncSend(String destination, Message message, SendCallback sendC * 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 destination formats: `topicName:tags` + * @param message {@link org.springframework.messaging.Message} * @param sendCallback {@link SendCallback} */ public void asyncSend(String destination, Message message, SendCallback sendCallback) { @@ -706,10 +698,10 @@ public void asyncSend(String destination, Message message, SendCallback sendC /** * 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 destination formats: `topicName:tags` + * @param payload the Object to use as payload * @param sendCallback {@link SendCallback} - * @param timeout send timeout with millis + * @param timeout send timeout with millis */ public void asyncSend(String destination, Object payload, SendCallback sendCallback, long timeout) { Message message = MessageBuilder.withPayload(payload).build(); @@ -719,8 +711,8 @@ public void asyncSend(String destination, Object payload, SendCallback sendCallb /** * Same to {@link #asyncSend(String, Message, SendCallback)}. * - * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @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) { @@ -731,11 +723,11 @@ public void asyncSend(String destination, Object payload, SendCallback sendCallb * 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 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 + * @param timeout send timeout with millis */ public void asyncSendOrderly(String destination, Message message, String hashKey, SendCallback sendCallback, long timeout) { @@ -746,8 +738,7 @@ public void asyncSendOrderly(String destination, Message message, String hash try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.send(rocketMsg, messageQueueSelector, hashKey, sendCallback, timeout); - } - catch (Exception e) { + } catch (Exception e) { log.error("asyncSendOrderly failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -756,9 +747,9 @@ public void asyncSendOrderly(String destination, Message message, String hash /** * 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 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) { @@ -768,9 +759,9 @@ public void asyncSendOrderly(String destination, Message message, String hash /** * 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 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) { @@ -780,11 +771,11 @@ public void asyncSendOrderly(String destination, Object payload, String hashKey, /** * 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 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 + * @param timeout send timeout with millis */ public void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback, long timeout) { @@ -799,7 +790,7 @@ public void asyncSendOrderly(String destination, Object payload, String hashKey, * 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} + * @param message {@link org.springframework.messaging.Message} */ public void sendOneWay(String destination, Message message) { if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { @@ -809,8 +800,7 @@ public void sendOneWay(String destination, Message message) { try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.sendOneway(rocketMsg); - } - catch (Exception e) { + } catch (Exception e) { log.error("sendOneWay failed. destination:{}, message:{} ", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -820,7 +810,7 @@ public void sendOneWay(String destination, Message message) { * Same to {@link #sendOneWay(String, Message)} * * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @param payload the Object to use as payload */ public void sendOneWay(String destination, Object payload) { Message message = MessageBuilder.withPayload(payload).build(); @@ -831,8 +821,8 @@ public void sendOneWay(String destination, Object payload) { * 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 ... + * @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())) { @@ -842,8 +832,7 @@ public void sendOneWayOrderly(String destination, Message message, String has try { org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); producer.sendOneway(rocketMsg, messageQueueSelector, hashKey); - } - catch (Exception e) { + } catch (Exception e) { log.error("sendOneWayOrderly failed. destination:{}, message:{}", destination, message); throw new MessagingException(e.getMessage(), e); } @@ -853,7 +842,7 @@ public void sendOneWayOrderly(String destination, Message message, String has * Same to {@link #sendOneWayOrderly(String, Message, String)} * * @param destination formats: `topicName:tags` - * @param payload the Object to use as payload + * @param payload the Object to use as payload */ public void sendOneWayOrderly(String destination, Object payload, String hashKey) { Message message = MessageBuilder.withPayload(payload).build(); @@ -894,21 +883,20 @@ public void destroy() { * Send Spring Message in Transaction * * @param destination destination formats: `topicName:tags` - * @param message message {@link org.springframework.messaging.Message} - * @param arg ext arg + * @param message message {@link org.springframework.messaging.Message} + * @param arg ext arg * @return TransactionSendResult * @throws MessagingException */ public TransactionSendResult sendMessageInTransaction(final String destination, final Message message, final Object arg) throws MessagingException { try { - if (((TransactionMQProducer)producer).getTransactionListener() == null) { + if (((TransactionMQProducer) producer).getTransactionListener() == null) { throw new IllegalStateException("The rocketMQTemplate does not exist TransactionListener"); } org.apache.rocketmq.common.message.Message rocketMsg = this.createRocketMqMessage(destination, message); return producer.sendMessageInTransaction(rocketMsg, arg); - } - catch (MQClientException e) { + } catch (MQClientException e) { throw RocketMQUtil.convert(e); } } @@ -923,29 +911,24 @@ private org.apache.rocketmq.common.message.Message createRocketMqMessage( private Object doConvertMessage(MessageExt messageExt, Type type) { if (Objects.equals(type, MessageExt.class)) { return messageExt; - } - else if (Objects.equals(type, byte[].class)) { + } else if (Objects.equals(type, byte[].class)) { return messageExt.getBody(); - } - else { + } else { String str = new String(messageExt.getBody(), Charset.forName(charset)); if (Objects.equals(type, String.class)) { return str; - } - else { + } else { // If msgType not string, use objectMapper change it. try { if (type instanceof Class) { //if the messageType has not Generic Parameter - return this.getMessageConverter().fromMessage(MessageBuilder.withPayload(str).build(), (Class)type); - } - else { + return this.getMessageConverter().fromMessage(MessageBuilder.withPayload(str).build(), (Class) type); + } else { //if the messageType has Generic Parameter, then use SmartMessageConverter#fromMessage with third parameter "conversionHint". //we have validate the MessageConverter is SmartMessageConverter in this#getMethodParameter. - return ((SmartMessageConverter)this.getMessageConverter()).fromMessage(MessageBuilder.withPayload(str).build(), (Class)((ParameterizedType)type).getRawType(), null); + return ((SmartMessageConverter) this.getMessageConverter()).fromMessage(MessageBuilder.withPayload(str).build(), (Class) ((ParameterizedType) type).getRawType(), null); } - } - catch (Exception e) { + } catch (Exception e) { log.error("convert failed. str:{}, msgType:{}", str, type); throw new RuntimeException("cannot convert message to " + type, e); } @@ -960,7 +943,7 @@ private Type getMessageType(RocketMQLocalRequestCallback rocketMQLocalRequestCal Type[] interfaces = targetClass.getGenericInterfaces(); if (Objects.nonNull(interfaces)) { for (Type type : interfaces) { - if (type instanceof ParameterizedType && (Objects.equals(((ParameterizedType)type).getRawType(), RocketMQLocalRequestCallback.class))) { + if (type instanceof ParameterizedType && (Objects.equals(((ParameterizedType) type).getRawType(), RocketMQLocalRequestCallback.class))) { matchedGenericInterface = type; break; } @@ -972,10 +955,10 @@ private Type getMessageType(RocketMQLocalRequestCallback rocketMQLocalRequestCal return Object.class; } - Type[] actualTypeArguments = ((ParameterizedType)matchedGenericInterface).getActualTypeArguments(); + Type[] actualTypeArguments = ((ParameterizedType) matchedGenericInterface).getActualTypeArguments(); if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) { return actualTypeArguments[0]; } return Object.class; } -} +} \ No newline at end of file From 1464698a8b03d5700d41efe9258c33acf14b8e81 Mon Sep 17 00:00:00 2001 From: rongtong Date: Fri, 3 Apr 2020 20:52:15 +0800 Subject: [PATCH 074/105] [ISSUE #241] Make the unit of consumeTimeout in rocketmq-spring consistent with rocketmq client --- .../rocketmq/spring/annotation/RocketMQMessageListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index f1c77485..7b7ff9ad 100644 --- 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 @@ -76,9 +76,9 @@ int consumeThreadMax() default 64; /** - * Max consumer timeout, default 30s. + * Maximum amount of time in minutes a message may block the consuming thread. */ - long consumeTimeout() default 30000L; + long consumeTimeout() default 15L; /** * The property of "access-key". From 8021ec3f1a06747ba395cf8fc61bc7d00b9d7077 Mon Sep 17 00:00:00 2001 From: zhangjidi Date: Fri, 5 Jun 2020 17:03:13 +0800 Subject: [PATCH 075/105] [ISSUE #263] Change the verions of rocketmq's client in the pom's file --- rocketmq-spring-boot-parent/pom.xml | 2 +- .../java/org/apache/rocketmq/spring/support/RocketMQUtil.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index 1b0130a8..b1e0d3cb 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -40,7 +40,7 @@ 2.1.1-SNAPSHOT - 4.6.0 + 4.7.0 1.7.25 2.9.7 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 index 5352b190..712323e3 100644 --- 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 @@ -29,6 +29,7 @@ import org.apache.rocketmq.client.producer.TransactionListener; import org.apache.rocketmq.client.producer.TransactionMQProducer; import org.apache.rocketmq.client.trace.AsyncTraceDispatcher; +import org.apache.rocketmq.client.trace.TraceDispatcher; import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl; import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.common.message.Message; @@ -268,7 +269,7 @@ public static DefaultMQProducer createDefaultMQProducer(String groupName, String if (isEnableMsgTrace) { try { - AsyncTraceDispatcher dispatcher = new AsyncTraceDispatcher(customizedTraceTopic, isEnableAcl ? new AclClientRPCHook(new SessionCredentials(ak, sk)) : null); + AsyncTraceDispatcher dispatcher = new AsyncTraceDispatcher(groupName, TraceDispatcher.Type.PRODUCE, customizedTraceTopic, isEnableAcl ? new AclClientRPCHook(new SessionCredentials(ak, sk)) : null); dispatcher.setHostProducer(producer.getDefaultMQProducerImpl()); Field field = DefaultMQProducer.class.getDeclaredField("traceDispatcher"); field.setAccessible(true); From 603903c2eb199ee9165e81e1f4eea9694399a551 Mon Sep 17 00:00:00 2001 From: zhangjidi Date: Mon, 8 Jun 2020 14:37:31 +0800 Subject: [PATCH 076/105] [ISSUE #262] Sending messages asynchronously use a custom AsyncSenderExecutor in RocketMQTemplate. --- .../spring/core/RocketMQTemplate.java | 6 +++ .../spring/core/RocketMQTemplateTest.java | 39 +++++++++++++++++++ 2 files changed, 45 insertions(+) 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 6683f101..78f0b2d7 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 @@ -24,6 +24,8 @@ import java.util.Collection; import java.util.Map; import java.util.Objects; +import java.util.concurrent.ExecutorService; + import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.MessageQueueSelector; @@ -86,6 +88,10 @@ public void setMessageQueueSelector(MessageQueueSelector messageQueueSelector) { this.messageQueueSelector = messageQueueSelector; } + public void setAsyncSenderExecutor(ExecutorService asyncSenderExecutor) { + this.producer.setAsyncSenderExecutor(asyncSenderExecutor); + } + /** * @param destination formats: `topicName:tags` * @param message {@link org.springframework.messaging.Message} the message to be sent. diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java index da6d7775..56a7de62 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java @@ -34,6 +34,13 @@ import org.springframework.messaging.support.MessageBuilder; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -87,6 +94,38 @@ public void testSendMessage() { } } + @Test + public void testSendMessage_withCustomAsyncSenderExecutor() { + ExecutorService executorService = new ThreadPoolExecutor( + 2, + 5, + 100, + TimeUnit.SECONDS, + new ArrayBlockingQueue(2000), + new ThreadFactory() { + private AtomicInteger threadIndex = new AtomicInteger(0); + + @Override + public Thread newThread(Runnable r) { + return new Thread(r, "AsyncSenderExecutor_" + this.threadIndex.incrementAndGet()); + } + }); + rocketMQTemplate.setAsyncSenderExecutor(executorService); + try { + rocketMQTemplate.asyncSend(topic, "payload", new SendCallback() { + @Override public void onSuccess(SendResult sendResult) { + + } + + @Override public void onException(Throwable e) { + + } + }); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); + } + } + @Test public void testSendAndReceive_NullMessage() { try { From a334685bd98886f669f42a205376cb7327ad6b96 Mon Sep 17 00:00:00 2001 From: L1 L31 Date: Sun, 28 Jun 2020 17:09:28 +0800 Subject: [PATCH 077/105] [ISSUE #271] AccessKey and screctKey is wrong when create procducer --- .../spring/autoconfigure/ExtProducerResetConfiguration.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java index a0cc706c..58d5eae0 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -110,9 +110,9 @@ private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annota groupName = StringUtils.isEmpty(groupName) ? producerConfig.getGroup() : groupName; String ak = environment.resolvePlaceholders(annotation.accessKey()); - ak = StringUtils.isEmpty(ak) ? producerConfig.getAccessKey() : annotation.accessKey(); + ak = StringUtils.isEmpty(ak) ? producerConfig.getAccessKey() : ak; String sk = environment.resolvePlaceholders(annotation.secretKey()); - sk = StringUtils.isEmpty(sk) ? producerConfig.getSecretKey() : annotation.secretKey(); + sk = StringUtils.isEmpty(sk) ? producerConfig.getSecretKey() : sk; boolean isEnableMsgTrace = annotation.enableMsgTrace(); String customizedTraceTopic = environment.resolvePlaceholders(annotation.customizedTraceTopic()); customizedTraceTopic = StringUtils.isEmpty(customizedTraceTopic) ? producerConfig.getCustomizedTraceTopic() : customizedTraceTopic; From fc9679f77c4e2f619c7c71e13c90d5cec6b10af8 Mon Sep 17 00:00:00 2001 From: rongtong Date: Fri, 17 Jul 2020 20:04:33 +0800 Subject: [PATCH 078/105] [ISSUE #282] Upgrade RocketMQ version to 4.7.1 --- rocketmq-spring-boot-parent/pom.xml | 2 +- .../rocketmq/spring/autoconfigure/RocketMQProperties.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index b1e0d3cb..7b990d6a 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -40,7 +40,7 @@ 2.1.1-SNAPSHOT - 4.7.0 + 4.7.1 1.7.25 2.9.7 diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java index 19573898..c08b3773 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java @@ -17,7 +17,7 @@ package org.apache.rocketmq.spring.autoconfigure; -import org.apache.rocketmq.common.MixAll; +import org.apache.rocketmq.common.topic.TopicValidator; import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.HashMap; @@ -130,7 +130,7 @@ public static class Producer { /** * The name value of message trace topic.If you don't config,you can use the default trace topic name. */ - private String customizedTraceTopic = MixAll.RMQ_SYS_TRACE_TOPIC; + private String customizedTraceTopic = TopicValidator.RMQ_SYS_TRACE_TOPIC; public String getGroup() { return group; From b4cd289d5445dd75592d0cfbfdb45f454d1ec5d3 Mon Sep 17 00:00:00 2001 From: iapplejohn Date: Tue, 21 Jul 2020 11:19:16 +0800 Subject: [PATCH 079/105] [ISSUE #285] Upgrade jackson/fastjson version --- rocketmq-spring-boot-parent/pom.xml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index 7b990d6a..22d37144 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -42,7 +42,8 @@ 4.7.1 1.7.25 - 2.9.7 + 2.11.1 + 1.2.72 1.8 @ @@ -161,6 +162,12 @@ jackson-databind ${jackson.version} + + + com.alibaba + fastjson + ${fastjson.version} + From 6936f74f48fc544d7df000fe8c3b026eb266e4c8 Mon Sep 17 00:00:00 2001 From: RongtongJin <794220751@qq.com> Date: Tue, 21 Jul 2020 13:10:14 +0800 Subject: [PATCH 080/105] [maven-release-plugin] prepare release rocketmq-spring-all-2.1.1 --- pom.xml | 4 ++-- rocketmq-spring-boot-parent/pom.xml | 4 ++-- rocketmq-spring-boot-starter/pom.xml | 2 +- rocketmq-spring-boot/pom.xml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 9b706227..f0ea8961 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.1.1-SNAPSHOT + 2.1.1 pom Apache RocketMQ Spring Boot ${project.version} @@ -39,7 +39,7 @@ git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git - HEAD + rocketmq-spring-all-2.1.1 diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index 22d37144..db54c46e 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.1.1-SNAPSHOT + 2.1.1 ../pom.xml @@ -38,7 +38,7 @@ 2.0.5.RELEASE 5.1.0.RELEASE - 2.1.1-SNAPSHOT + 2.1.1 4.7.1 1.7.25 diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml index b221f96b..6b5bfe4a 100644 --- a/rocketmq-spring-boot-starter/pom.xml +++ b/rocketmq-spring-boot-starter/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.1.1-SNAPSHOT + 2.1.1 ../rocketmq-spring-boot-parent/pom.xml diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml index 0c22dd7a..3cad2834 100644 --- a/rocketmq-spring-boot/pom.xml +++ b/rocketmq-spring-boot/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.1.1-SNAPSHOT + 2.1.1 ../rocketmq-spring-boot-parent/pom.xml From 6e8e49ea0411bff5c07f60136258ca888c481017 Mon Sep 17 00:00:00 2001 From: RongtongJin <794220751@qq.com> Date: Tue, 21 Jul 2020 13:10:38 +0800 Subject: [PATCH 081/105] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- rocketmq-spring-boot-parent/pom.xml | 4 ++-- rocketmq-spring-boot-starter/pom.xml | 2 +- rocketmq-spring-boot/pom.xml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index f0ea8961..f7698bcc 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.1.1 + 2.1.2-SNAPSHOT pom Apache RocketMQ Spring Boot ${project.version} @@ -39,7 +39,7 @@ git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git - rocketmq-spring-all-2.1.1 + HEAD diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index db54c46e..f0d7b1dd 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.1.1 + 2.1.2-SNAPSHOT ../pom.xml @@ -38,7 +38,7 @@ 2.0.5.RELEASE 5.1.0.RELEASE - 2.1.1 + 2.1.2-SNAPSHOT 4.7.1 1.7.25 diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml index 6b5bfe4a..c0e6b8a3 100644 --- a/rocketmq-spring-boot-starter/pom.xml +++ b/rocketmq-spring-boot-starter/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.1.1 + 2.1.2-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml index 3cad2834..9627b14b 100644 --- a/rocketmq-spring-boot/pom.xml +++ b/rocketmq-spring-boot/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.1.1 + 2.1.2-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml From 8f24a5cd416e9ea39f76e8f105b6ec09feee96f8 Mon Sep 17 00:00:00 2001 From: rongtong Date: Wed, 12 Aug 2020 10:19:12 +0800 Subject: [PATCH 082/105] [ISSUE# 289] Use the default instance name when using acl (#290) * chore(consumer): Use the default instance name when using acl * chore(version): update example rocketmq version to 2.1.2-SNAPSHOT --- rocketmq-spring-boot-samples/pom.xml | 2 +- .../support/DefaultRocketMQListenerContainer.java | 1 - .../apache/rocketmq/spring/support/RocketMQUtil.java | 12 ------------ .../rocketmq/spring/support/RocketMQUtilTest.java | 10 ---------- 4 files changed, 1 insertion(+), 24 deletions(-) diff --git a/rocketmq-spring-boot-samples/pom.xml b/rocketmq-spring-boot-samples/pom.xml index ca74d548..52ee175c 100644 --- a/rocketmq-spring-boot-samples/pom.xml +++ b/rocketmq-spring-boot-samples/pom.xml @@ -24,7 +24,7 @@ org.apache.rocketmq rocketmq-spring-boot-samples pom - 2.1.1-SNAPSHOT + 2.1.2-SNAPSHOT RocketMQ Spring Boot Samples Samples for RocketMQ Spring Boot 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 2642d07b..dff5e0c6 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 @@ -555,7 +555,6 @@ private void initRocketMQPushConsumer() throws MQClientException { enableMsgTrace, this.applicationContext.getEnvironment(). resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); consumer.setVipChannelEnabled(false); - consumer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, consumerGroup)); } else { log.debug("Access-key or secret-key not configure in " + this + "."); consumer = new DefaultMQPushConsumer(consumerGroup, enableMsgTrace, 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 index 712323e3..311e5e57 100644 --- 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 @@ -31,7 +31,6 @@ import org.apache.rocketmq.client.trace.AsyncTraceDispatcher; import org.apache.rocketmq.client.trace.TraceDispatcher; import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl; -import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.common.message.Message; import org.apache.rocketmq.common.message.MessageConst; import org.apache.rocketmq.common.message.MessageExt; @@ -244,17 +243,6 @@ public static RPCHook getRPCHookByAkSk(Environment env, String accessKeyOrExpr, return null; } - public static String getInstanceName(RPCHook rpcHook, String identify) { - String separator = "|"; - StringBuilder instanceName = new StringBuilder(); - SessionCredentials sessionCredentials = ((AclClientRPCHook) rpcHook).getSessionCredentials(); - instanceName.append(sessionCredentials.getAccessKey()) - .append(separator).append(sessionCredentials.getSecretKey()) - .append(separator).append(identify) - .append(separator).append(UtilAll.getPid()); - return instanceName.toString(); - } - public static DefaultMQProducer createDefaultMQProducer(String groupName, String ak, String sk, boolean isEnableMsgTrace, String customizedTraceTopic) { 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 index 41b09226..42439ad8 100644 --- 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 @@ -130,14 +130,4 @@ public void testConvertToSpringMessage() { assertEquals("tagA", message.getHeaders().get(toRocketHeaderKey(RocketMQHeaders.TAGS))); assertEquals("key1", message.getHeaders().get(toRocketHeaderKey(RocketMQHeaders.KEYS))); } - - @Test - public void testGetInstanceName() { - String ak = "ak"; - String sk = "sk"; - String consumerGroup = "consumerGroup"; - RPCHook rpcHook = new AclClientRPCHook(new SessionCredentials(ak, sk)); - String expected = "ak|sk|consumerGroup|"; - assertEquals(expected + UtilAll.getPid(), RocketMQUtil.getInstanceName(rpcHook, consumerGroup)); - } } \ No newline at end of file From ba300d1f74b003e25e53b6c00178164dd8abfc56 Mon Sep 17 00:00:00 2001 From: "jun.chen" <33209018+cj-8480@users.noreply.github.com> Date: Thu, 17 Sep 2020 14:06:00 +0800 Subject: [PATCH 083/105] [ISSUE #294] GetAndWrapmessage method in rocketmqUtil is missing prefix when getting keys --- .../java/org/apache/rocketmq/spring/support/RocketMQUtil.java | 4 ++++ 1 file changed, 4 insertions(+) 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 index 311e5e57..7d25acd5 100644 --- 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 @@ -170,6 +170,10 @@ private static Message getAndWrapMessage(String destination, MessageHeaders head Message rocketMsg = new Message(topic, tags, payloads); if (Objects.nonNull(headers) && !headers.isEmpty()) { Object keys = headers.get(RocketMQHeaders.KEYS); + // if headers not have 'KEYS', try add prefix when getting keys + if (StringUtils.isEmpty(keys)) { + keys = headers.get(toRocketHeaderKey(RocketMQHeaders.KEYS)); + } if (!StringUtils.isEmpty(keys)) { // if headers has 'KEYS', set rocketMQ message key rocketMsg.setKeys(keys.toString()); } From 3cc554b62f2f8a88efa38aecd3e52d985eb49654 Mon Sep 17 00:00:00 2001 From: zhangjidi2016 Date: Tue, 27 Oct 2020 20:45:32 +0800 Subject: [PATCH 084/105] [ISSUE #298] Too many warning info when consuming failed. (#302) --- .../spring/support/DefaultRocketMQListenerContainer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 dff5e0c6..89b9b913 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 @@ -355,7 +355,7 @@ public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeCo long costTime = System.currentTimeMillis() - now; log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime); } catch (Exception e) { - log.warn("consume message failed. messageExt:{}, error:{}", messageExt, e); + log.warn("consume message failed. messageId:{}, topic:{}, reconsumeTimes:{}", messageExt.getMsgId(), messageExt.getTopic(), messageExt.getReconsumeTimes(), e); context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); return ConsumeConcurrentlyStatus.RECONSUME_LATER; } @@ -378,7 +378,7 @@ public ConsumeOrderlyStatus consumeMessage(List msgs, ConsumeOrderly long costTime = System.currentTimeMillis() - now; log.info("consume {} cost: {} ms", messageExt.getMsgId(), costTime); } catch (Exception e) { - log.warn("consume message failed. messageExt:{}", messageExt, e); + log.warn("consume message failed. messageId:{}, topic:{}, reconsumeTimes:{}", messageExt.getMsgId(), messageExt.getTopic(), messageExt.getReconsumeTimes(), e); context.setSuspendCurrentQueueTimeMillis(suspendCurrentQueueTimeMillis); return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; } From 78dd2d9d3ca2b3f225bbb0fb50c382d1f9121b45 Mon Sep 17 00:00:00 2001 From: zhangjidi2016 Date: Wed, 28 Oct 2020 09:49:26 +0800 Subject: [PATCH 085/105] [ISSUE #268] RocketMQMessageListener nameServer not work (#301) * [ISSUE #268] RocketMQMessageListener nameServer not work * Use the separator '@' --- .../spring/support/DefaultRocketMQListenerContainer.java | 2 ++ .../org/apache/rocketmq/spring/support/RocketMQUtil.java | 9 +++++++++ .../apache/rocketmq/spring/support/RocketMQUtilTest.java | 7 +++++++ 3 files changed, 18 insertions(+) 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 89b9b913..952b4e1f 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 @@ -561,6 +561,8 @@ private void initRocketMQPushConsumer() throws MQClientException { this.applicationContext.getEnvironment(). resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); } + + consumer.setInstanceName(RocketMQUtil.getInstanceName(nameServer)); String customizedNameServer = this.applicationContext.getEnvironment().resolveRequiredPlaceholders(this.rocketMQMessageListener.nameServer()); if (customizedNameServer != null) { 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 index 7d25acd5..082b0f68 100644 --- 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 @@ -31,6 +31,7 @@ import org.apache.rocketmq.client.trace.AsyncTraceDispatcher; import org.apache.rocketmq.client.trace.TraceDispatcher; import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl; +import org.apache.rocketmq.common.UtilAll; import org.apache.rocketmq.common.message.Message; import org.apache.rocketmq.common.message.MessageConst; import org.apache.rocketmq.common.message.MessageExt; @@ -275,5 +276,13 @@ public static DefaultMQProducer createDefaultMQProducer(String groupName, String return producer; } + + public static String getInstanceName(String identify) { + char separator = '@'; + StringBuilder instanceName = new StringBuilder(); + instanceName.append(identify) + .append(separator).append(UtilAll.getPid()); + return instanceName.toString(); + } } 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 index 42439ad8..e5584836 100644 --- 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 @@ -130,4 +130,11 @@ public void testConvertToSpringMessage() { assertEquals("tagA", message.getHeaders().get(toRocketHeaderKey(RocketMQHeaders.TAGS))); assertEquals("key1", message.getHeaders().get(toRocketHeaderKey(RocketMQHeaders.KEYS))); } + + @Test + public void testGetInstanceName() { + String nameServer = "127.0.0.1:9876"; + String expected = "127.0.0.1:9876@"; + assertEquals(expected + UtilAll.getPid(), RocketMQUtil.getInstanceName(nameServer)); + } } \ No newline at end of file From 77518d298f32b6ce49c5b42a07eec1e18f285c81 Mon Sep 17 00:00:00 2001 From: CharliePu Date: Wed, 11 Nov 2020 07:53:42 +0800 Subject: [PATCH 086/105] [ISSUE #304] Fix the correspondence between enumerations and numbers. --- .../rocketmq/samples/springboot/ProducerApplication.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 46ac5abe..f8140d41 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 @@ -257,13 +257,13 @@ public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { if (null != status) { switch (status) { case 0: - retState = RocketMQLocalTransactionState.UNKNOWN; + retState = RocketMQLocalTransactionState.COMMIT; break; case 1: - retState = RocketMQLocalTransactionState.COMMIT; + retState = RocketMQLocalTransactionState.ROLLBACK; break; case 2: - retState = RocketMQLocalTransactionState.ROLLBACK; + retState = RocketMQLocalTransactionState.UNKNOWN; break; } } From 312bfc9c0afc0ac221fb9e8547543ac35855529f Mon Sep 17 00:00:00 2001 From: CharliePu Date: Tue, 17 Nov 2020 16:10:43 +0800 Subject: [PATCH 087/105] [ISSUE #308] Fix the comment error in ACLStringConsumer class --- .../apache/rocketmq/samples/springboot/ACLStringConsumer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ACLStringConsumer.java b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ACLStringConsumer.java index fe99d389..d2d654f0 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ACLStringConsumer.java +++ b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ACLStringConsumer.java @@ -29,7 +29,7 @@ topic = "normal_topic_define_in_Aliware_MQ", consumerGroup = "group_define_in_Aliware_MQ" //accessKey = "AK" // It will read by `rocketmq.consumer.access-key` key - //secretKey = "SK" // It will read by `rocketmq.consumer.access-key` key + //secretKey = "SK" // It will read by `rocketmq.consumer.secret-key` key ) public class ACLStringConsumer implements RocketMQListener { @Override From 5404f269e37e2c5ac52d44a84c302f4ba9999700 Mon Sep 17 00:00:00 2001 From: WreathCrystal <24571465@qq.com> Date: Wed, 25 Nov 2020 16:09:51 +0800 Subject: [PATCH 088/105] Change parent.version 2.1.1 to 2.1.2 --- rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml index 07117783..041ee964 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml +++ b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml @@ -23,7 +23,7 @@ org.apache.rocketmq rocketmq-spring-boot-samples - 2.1.1-SNAPSHOT + 2.1.2-SNAPSHOT rocketmq-consume-acl-demo From 9b41cfe99d3ff829350b62a8892c346af9160fad Mon Sep 17 00:00:00 2001 From: WreathCrystal <24571465@qq.com> Date: Wed, 25 Nov 2020 16:10:06 +0800 Subject: [PATCH 089/105] Change parent.version 2.1.1 to 2.1.2 --- rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml b/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml index a63328af..69a569b5 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml @@ -23,7 +23,7 @@ org.apache.rocketmq rocketmq-spring-boot-samples - 2.1.1-SNAPSHOT + 2.1.2-SNAPSHOT rocketmq-consume-demo From 62c74a9a5d06fe2b7e3ee29e1470c42d9bfd16e7 Mon Sep 17 00:00:00 2001 From: WreathCrystal <24571465@qq.com> Date: Wed, 25 Nov 2020 16:10:23 +0800 Subject: [PATCH 090/105] Change parent.version 2.1.1 to 2.1.2 --- rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml b/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml index 4bc87c3a..08ebc6e9 100644 --- a/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml +++ b/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml @@ -23,7 +23,7 @@ org.apache.rocketmq rocketmq-spring-boot-samples - 2.1.1-SNAPSHOT + 2.1.2-SNAPSHOT rocketmq-produce-acl-demo From dba2f1e1b32f48caf87d32576c27b45a355d3f37 Mon Sep 17 00:00:00 2001 From: WreathCrystal <24571465@qq.com> Date: Wed, 25 Nov 2020 16:10:32 +0800 Subject: [PATCH 091/105] Change parent.version 2.1.1 to 2.1.2 --- rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml b/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml index 05de2f8f..f888b14a 100644 --- a/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml +++ b/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml @@ -23,7 +23,7 @@ org.apache.rocketmq rocketmq-spring-boot-samples - 2.1.1-SNAPSHOT + 2.1.2-SNAPSHOT rocketmq-produce-demo From 9561d394c409cf84bad01de91b54a9415ca893c8 Mon Sep 17 00:00:00 2001 From: von gosling Date: Thu, 26 Nov 2020 16:36:08 +0800 Subject: [PATCH 092/105] Remove unused import --- .../samples/springboot/consumer/ConsumerWithReplyBytes.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyBytes.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyBytes.java index 850fbd33..ad79c84f 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyBytes.java +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ConsumerWithReplyBytes.java @@ -20,8 +20,6 @@ import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQReplyListener; -import org.springframework.messaging.Message; -import org.springframework.messaging.support.MessageBuilder; import org.springframework.stereotype.Service; /** From b063d8763be610bc852934d6493776f141e547dd Mon Sep 17 00:00:00 2001 From: von gosling Date: Thu, 26 Nov 2020 16:37:26 +0800 Subject: [PATCH 093/105] Remove unused import --- .../samples/springboot/consumer/ObjectConsumerWithReplyUser.java | 1 - 1 file changed, 1 deletion(-) diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ObjectConsumerWithReplyUser.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ObjectConsumerWithReplyUser.java index f66b003b..e36fd665 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ObjectConsumerWithReplyUser.java +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/ObjectConsumerWithReplyUser.java @@ -17,7 +17,6 @@ package org.apache.rocketmq.samples.springboot.consumer; -import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.samples.springboot.domain.User; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQReplyListener; From 7ee4ba19bcac1d721b0eb1cfd3187ba7b90141d3 Mon Sep 17 00:00:00 2001 From: von gosling Date: Thu, 26 Nov 2020 16:39:43 +0800 Subject: [PATCH 094/105] Remove unused import --- .../springboot/consumer/StringConsumerWithReplyString.java | 1 - 1 file changed, 1 deletion(-) diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerWithReplyString.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerWithReplyString.java index b194bc6e..a57f20db 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerWithReplyString.java +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerWithReplyString.java @@ -17,7 +17,6 @@ package org.apache.rocketmq.samples.springboot.consumer; -import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQReplyListener; import org.springframework.stereotype.Service; From cf18bb1ab68e28c67e72b37eadf3935979086793 Mon Sep 17 00:00:00 2001 From: von gosling Date: Thu, 26 Nov 2020 16:41:28 +0800 Subject: [PATCH 095/105] Default choice is not allowed to merge --- .github/PULL_REQUEST_TEMPLATE.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 5799172d..9087fa0f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -12,9 +12,9 @@ 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. -- [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. +- [] 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. +- [] 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. +- [] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. +- [] Write necessary unit-test(over 80% coverage) to verify your logic correction, more mock a little better when cross module dependency exist. +- [] 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). From 666a26f61b7a57f10eec9eaad62f9a5258286aef Mon Sep 17 00:00:00 2001 From: von gosling Date: Thu, 26 Nov 2020 16:43:16 +0800 Subject: [PATCH 096/105] 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 9087fa0f..870aadbb 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -17,4 +17,4 @@ Follow this checklist to help us incorporate your contribution quickly and easil - [] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. - [] Write necessary unit-test(over 80% coverage) to verify your logic correction, more mock a little better when cross module dependency exist. - [] 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). +- [] If this contribution is large, please file an [Apache Individual Contributor License Agreement](http://www.apache.org/licenses/#clas). From 544205c9821e0bb9005bb20d3bfeaeffddf92cd5 Mon Sep 17 00:00:00 2001 From: von gosling Date: Thu, 26 Nov 2020 18:48:03 +0800 Subject: [PATCH 097/105] Update pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f7698bcc..e97ff8d8 100644 --- a/pom.xml +++ b/pom.xml @@ -104,7 +104,7 @@ org.jacoco jacoco-maven-plugin - 0.7.8 + 0.8.0 default-prepare-agent From 4cab092238f31161aaa595bce15e21259233ef0e Mon Sep 17 00:00:00 2001 From: von gosling Date: Thu, 26 Nov 2020 18:49:05 +0800 Subject: [PATCH 098/105] Update pom.xml --- rocketmq-spring-boot-samples/pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rocketmq-spring-boot-samples/pom.xml b/rocketmq-spring-boot-samples/pom.xml index 52ee175c..3d8978c6 100644 --- a/rocketmq-spring-boot-samples/pom.xml +++ b/rocketmq-spring-boot-samples/pom.xml @@ -38,6 +38,8 @@ + 1.8 + 1.8 2.1.0 @@ -60,7 +62,6 @@ validate validate - ${disable.checks} src/main/resources style/rmq_checkstyle.xml UTF-8 From d20b01c140dbed878a3506f46d674751f23f43d0 Mon Sep 17 00:00:00 2001 From: von gosling Date: Thu, 26 Nov 2020 19:12:54 +0800 Subject: [PATCH 099/105] Update jacoco to the latest version to support jdk 11 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e97ff8d8..5b998825 100644 --- a/pom.xml +++ b/pom.xml @@ -104,7 +104,7 @@ org.jacoco jacoco-maven-plugin - 0.8.0 + 0.8.6 default-prepare-agent From af9f20eabd2c4ae1245bed2c0b816592128b1388 Mon Sep 17 00:00:00 2001 From: CharliePu Date: Fri, 4 Dec 2020 14:06:53 +0800 Subject: [PATCH 100/105] [ISSUE #306] Support real LitePullMessage in RocketMQ-Spring (#307) * Support LitePullMessage in RocketMQ-Spring * Add a property in litePullConnsumer named pullBatchSize. * Add necessary comments. --- .../springboot/ConsumerACLApplication.java | 17 +- .../src/main/resources/application.properties | 2 + .../springboot/ConsumerApplication.java | 24 ++- .../springboot/ExtRocketMQTemplate.java | 24 +++ .../src/main/resources/application.properties | 2 + .../ExtRocketMQConsumerConfiguration.java | 97 ++++++++++++ .../ExtConsumerResetConfiguration.java | 149 ++++++++++++++++++ .../RocketMQAutoConfiguration.java | 80 +++++++++- .../autoconfigure/RocketMQProperties.java | 105 ++++++++++++ .../spring/core/RocketMQTemplate.java | 88 +++++++++-- .../rocketmq/spring/support/RocketMQUtil.java | 56 ++++++- .../RocketMQAutoConfigurationTest.java | 66 ++++++++ .../spring/core/ExtRocketMQTemplateTest.java | 18 ++- .../spring/core/RocketMQTemplateTest.java | 16 +- 14 files changed, 718 insertions(+), 26 deletions(-) create mode 100644 rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/ExtRocketMQTemplate.java create mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ExtRocketMQConsumerConfiguration.java create mode 100644 rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtConsumerResetConfiguration.java diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerACLApplication.java b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerACLApplication.java index 3bf266b1..f3d75783 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerACLApplication.java +++ b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerACLApplication.java @@ -17,17 +17,32 @@ package org.apache.rocketmq.samples.springboot; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import javax.annotation.Resource; +import java.util.List; + /** * ConsumerApplication */ @SpringBootApplication -public class ConsumerACLApplication { +public class ConsumerACLApplication implements CommandLineRunner { + + @Resource + private RocketMQTemplate rocketMQTemplate; public static void main(String[] args) { SpringApplication.run(ConsumerACLApplication.class, args); } + + @Override + public void run(String... args) throws Exception { + ////This is an example of pull consumer with access-key and secret-key. + List messages = rocketMQTemplate.receive(String.class); + System.out.printf("receive from rocketMQTemplate, messages=%s %n", messages); + } } diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/resources/application.properties b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/resources/application.properties index 057edebc..3fe6abbe 100644 --- a/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/resources/application.properties +++ b/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/resources/application.properties @@ -17,6 +17,8 @@ spring.application.name=rocketmq-consume-acl-demo rocketmq.name-server=Endpoint_of_Aliware_MQ +rocketmq.consumer.group=my-group1 +rocketmq.consumer.topic=test rocketmq.topic=normal_topic_define_in_Aliware_MQ # properties used in application code 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 index e4fbc8c9..6435d478 100644 --- 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 @@ -17,17 +17,39 @@ package org.apache.rocketmq.samples.springboot; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import javax.annotation.Resource; +import java.util.List; + /** * ConsumerApplication */ @SpringBootApplication -public class ConsumerApplication { +public class ConsumerApplication implements CommandLineRunner { + + @Resource + private RocketMQTemplate rocketMQTemplate; + + @Resource(name = "extRocketMQTemplate") + private RocketMQTemplate extRocketMQTemplate; public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); } + + @Override + public void run(String... args) throws Exception { + //This is an example of pull consumer using rocketMQTemplate. + List messages = rocketMQTemplate.receive(String.class); + System.out.printf("receive from rocketMQTemplate, messages=%s %n", messages); + + //This is an example of pull consumer using extRocketMQTemplate. + messages = extRocketMQTemplate.receive(String.class); + System.out.printf("receive from extRocketMQTemplate, messages=%s %n", messages); + } } diff --git a/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/ExtRocketMQTemplate.java b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/ExtRocketMQTemplate.java new file mode 100644 index 00000000..5499ac1c --- /dev/null +++ b/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/ExtRocketMQTemplate.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.samples.springboot; + +import org.apache.rocketmq.spring.annotation.ExtRocketMQConsumerConfiguration; +import org.apache.rocketmq.spring.core.RocketMQTemplate; + +@ExtRocketMQConsumerConfiguration(topic = "${demo.rocketmq.topic}", group = "string_consumer") +public class ExtRocketMQTemplate extends RocketMQTemplate { +} \ No newline at end of file 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 096cbb50..5953e487 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 @@ -16,6 +16,8 @@ spring.application.name=rocketmq-consume-demo rocketmq.name-server=localhost:9876 +rocketmq.consumer.group=my-group1 +rocketmq.consumer.topic=test # properties used in application code demo.rocketmq.topic=string-topic demo.rocketmq.bytesRequestTopic=bytesRequestTopic diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ExtRocketMQConsumerConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ExtRocketMQConsumerConfiguration.java new file mode 100644 index 00000000..63e4e371 --- /dev/null +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ExtRocketMQConsumerConfiguration.java @@ -0,0 +1,97 @@ +/* + * 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.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; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Component +public @interface ExtRocketMQConsumerConfiguration { + + String NAME_SERVER_PLACEHOLDER = "${rocketmq.name-server:}"; + String GROUP_PLACEHOLDER = "${rocketmq.consumer.group:}"; + String TOPIC_PLACEHOLDER = "${rocketmq.consumer.topic:}"; + String ACCESS_CHANNEL_PLACEHOLDER = "${rocketmq.access-channel:}"; + String ACCESS_KEY_PLACEHOLDER = "${rocketmq.consumer.access-key:}"; + String SECRET_KEY_PLACEHOLDER = "${rocketmq.consumer.secret-key:}"; + + /** + * The component name of the Producer configuration. + */ + String value() default ""; + + /** + * The property of "name-server". + */ + String nameServer() default NAME_SERVER_PLACEHOLDER; + + /** + * The property of "access-channel". + */ + String accessChannel() default ACCESS_CHANNEL_PLACEHOLDER; + + /** + * Group name of consumer. + */ + String group() default GROUP_PLACEHOLDER; + + /** + * Topic name of consumer. + */ + String topic() default TOPIC_PLACEHOLDER; + + /** + * Control message mode, if you want all subscribers receive message all message, broadcasting is a good choice. + */ + MessageModel messageModel() default MessageModel.CLUSTERING; + + /** + * 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 "*"; + + /** + * The property of "access-key". + */ + String accessKey() default ACCESS_KEY_PLACEHOLDER; + + /** + * The property of "secret-key". + */ + String secretKey() default SECRET_KEY_PLACEHOLDER; + + /** + * Maximum number of messages pulled each time. + */ + int pullBatchSize() default 10; +} \ No newline at end of file diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtConsumerResetConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtConsumerResetConfiguration.java new file mode 100644 index 00000000..7e81b5bb --- /dev/null +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtConsumerResetConfiguration.java @@ -0,0 +1,149 @@ +/* + * 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.autoconfigure; + +import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.spring.annotation.ExtRocketMQConsumerConfiguration; +import org.apache.rocketmq.spring.annotation.MessageModel; +import org.apache.rocketmq.spring.annotation.SelectorType; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.apache.rocketmq.spring.support.RocketMQMessageConverter; +import org.apache.rocketmq.spring.support.RocketMQUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.framework.AopProxyUtils; +import org.springframework.aop.scope.ScopedProxyUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.SmartInitializingSingleton; +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; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import java.util.Map; +import java.util.stream.Collectors; + +@Configuration +public class ExtConsumerResetConfiguration implements ApplicationContextAware, SmartInitializingSingleton { + + private final static Logger log = LoggerFactory.getLogger(ExtConsumerResetConfiguration.class); + + private ConfigurableApplicationContext applicationContext; + + private StandardEnvironment environment; + + private RocketMQProperties rocketMQProperties; + + private RocketMQMessageConverter rocketMQMessageConverter; + + public ExtConsumerResetConfiguration(RocketMQMessageConverter rocketMQMessageConverter, + StandardEnvironment environment, RocketMQProperties rocketMQProperties) { + this.rocketMQMessageConverter = rocketMQMessageConverter; + this.environment = environment; + this.rocketMQProperties = rocketMQProperties; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = (ConfigurableApplicationContext) applicationContext; + } + + @Override + public void afterSingletonsInstantiated() { + Map beans = this.applicationContext + .getBeansWithAnnotation(ExtRocketMQConsumerConfiguration.class) + .entrySet().stream().filter(entry -> !ScopedProxyUtils.isScopedTarget(entry.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + beans.forEach(this::registerTemplate); + } + + private void registerTemplate(String beanName, Object bean) { + Class clazz = AopProxyUtils.ultimateTargetClass(bean); + + if (!RocketMQTemplate.class.isAssignableFrom(bean.getClass())) { + throw new IllegalStateException(clazz + " is not instance of " + RocketMQTemplate.class.getName()); + } + + ExtRocketMQConsumerConfiguration annotation = clazz.getAnnotation(ExtRocketMQConsumerConfiguration.class); + GenericApplicationContext genericApplicationContext = (GenericApplicationContext) applicationContext; + validate(annotation, genericApplicationContext); + + DefaultLitePullConsumer consumer = null; + try { + consumer = createConsumer(annotation); + // Set instanceName same as the beanName + consumer.setInstanceName(beanName); + consumer.start(); + } catch (Exception e) { + log.error("Failed to startup PullConsumer for RocketMQTemplate {}", beanName, e); + } + RocketMQTemplate rocketMQTemplate = (RocketMQTemplate) bean; + rocketMQTemplate.setConsumer(consumer); + rocketMQTemplate.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); + log.info("Set real consumer to :{} {}", beanName, annotation.value()); + } + + private DefaultLitePullConsumer createConsumer(ExtRocketMQConsumerConfiguration annotation) + throws MQClientException { + + RocketMQProperties.Consumer consumerConfig = rocketMQProperties.getConsumer(); + if (consumerConfig == null) { + consumerConfig = new RocketMQProperties.Consumer(); + } + String nameServer = resolvePlaceholders(annotation.nameServer(), rocketMQProperties.getNameServer()); + String groupName = resolvePlaceholders(annotation.group(), consumerConfig.getGroup()); + String topicName = resolvePlaceholders(annotation.topic(), consumerConfig.getTopic()); + Assert.hasText(nameServer, "[nameServer] must not be null"); + Assert.hasText(groupName, "[group] must not be null"); + Assert.hasText(topicName, "[topic] must not be null"); + + String accessChannel = resolvePlaceholders(annotation.accessChannel(), rocketMQProperties.getAccessChannel()); + MessageModel messageModel = annotation.messageModel(); + SelectorType selectorType = annotation.selectorType(); + String selectorExpression = annotation.selectorExpression(); + String ak = resolvePlaceholders(annotation.accessKey(), consumerConfig.getAccessKey()); + String sk = resolvePlaceholders(annotation.secretKey(), consumerConfig.getSecretKey()); + int pullBatchSize = annotation.pullBatchSize(); + + DefaultLitePullConsumer litePullConsumer = RocketMQUtil.createDefaultLitePullConsumer(nameServer, accessChannel, + groupName, topicName, messageModel, selectorType, selectorExpression, ak, sk, pullBatchSize); + return litePullConsumer; + } + + private String resolvePlaceholders(String text, String defaultValue) { + String value = environment.resolvePlaceholders(text); + return StringUtils.isEmpty(value) ? defaultValue : value; + } + + private void validate(ExtRocketMQConsumerConfiguration annotation, + GenericApplicationContext genericApplicationContext) { + if (genericApplicationContext.isBeanNameInUse(annotation.value())) { + throw new BeanDefinitionValidationException( + String.format("Bean {} has been used in Spring Application Context, " + + "please check the @ExtRocketMQConsumerConfiguration", + annotation.value())); + } + } +} \ No newline at end of file diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java index e6131e78..b9ec643e 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java @@ -17,47 +17,66 @@ package org.apache.rocketmq.spring.autoconfigure; -import javax.annotation.PostConstruct; import org.apache.rocketmq.client.AccessChannel; import org.apache.rocketmq.client.MQAdmin; +import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer; +import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.spring.annotation.MessageModel; +import org.apache.rocketmq.spring.annotation.SelectorType; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.apache.rocketmq.spring.support.RocketMQMessageConverter; import org.apache.rocketmq.spring.support.RocketMQUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; 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.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.core.env.Environment; import org.springframework.util.Assert; import org.springframework.util.StringUtils; +import javax.annotation.PostConstruct; + @Configuration @EnableConfigurationProperties(RocketMQProperties.class) @ConditionalOnClass({MQAdmin.class}) @ConditionalOnProperty(prefix = "rocketmq", value = "name-server", matchIfMissing = true) -@Import({MessageConverterConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class, RocketMQTransactionConfiguration.class}) +@Import({MessageConverterConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class, ExtConsumerResetConfiguration.class, RocketMQTransactionConfiguration.class}) @AutoConfigureAfter({MessageConverterConfiguration.class}) @AutoConfigureBefore({RocketMQTransactionConfiguration.class}) -public class RocketMQAutoConfiguration { +public class RocketMQAutoConfiguration implements ApplicationContextAware { private static final Logger log = LoggerFactory.getLogger(RocketMQAutoConfiguration.class); public static final String ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME = "rocketMQTemplate"; + public static final String PRODUCER_BEAN_NAME = "defaultMQProducer"; + public static final String CONSUMER_BEAN_NAME = "defaultLitePullConsumer"; @Autowired private Environment environment; + private ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + @PostConstruct public void checkProperties() { String nameServer = environment.getProperty("rocketmq.name-server", String.class); @@ -67,7 +86,7 @@ public void checkProperties() { } } - @Bean + @Bean(PRODUCER_BEAN_NAME) @ConditionalOnMissingBean(DefaultMQProducer.class) @ConditionalOnProperty(prefix = "rocketmq", value = {"name-server", "producer.group"}) public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties) { @@ -100,14 +119,59 @@ public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties return producer; } + @Bean(CONSUMER_BEAN_NAME) + @ConditionalOnMissingBean(DefaultLitePullConsumer.class) + @ConditionalOnProperty(prefix = "rocketmq", value = {"name-server", "consumer.group", "consumer.topic"}) + public DefaultLitePullConsumer defaultLitePullConsumer(RocketMQProperties rocketMQProperties) + throws MQClientException { + RocketMQProperties.Consumer consumerConfig = rocketMQProperties.getConsumer(); + String nameServer = rocketMQProperties.getNameServer(); + String groupName = consumerConfig.getGroup(); + String topicName = consumerConfig.getTopic(); + Assert.hasText(nameServer, "[rocketmq.name-server] must not be null"); + Assert.hasText(groupName, "[rocketmq.consumer.group] must not be null"); + Assert.hasText(topicName, "[rocketmq.consumer.topic] must not be null"); + + String accessChannel = rocketMQProperties.getAccessChannel(); + MessageModel messageModel = MessageModel.valueOf(consumerConfig.getMessageModel()); + SelectorType selectorType = SelectorType.valueOf(consumerConfig.getSelectorType()); + String selectorExpression = consumerConfig.getSelectorExpression(); + String ak = consumerConfig.getAccessKey(); + String sk = consumerConfig.getSecretKey(); + int pullBatchSize = consumerConfig.getPullBatchSize(); + + DefaultLitePullConsumer litePullConsumer = RocketMQUtil.createDefaultLitePullConsumer(nameServer, accessChannel, + groupName, topicName, messageModel, selectorType, selectorExpression, ak, sk, pullBatchSize); + return litePullConsumer; + } + @Bean(destroyMethod = "destroy") - @ConditionalOnBean(DefaultMQProducer.class) + @Conditional(ProducerOrConsumerPropertyCondition.class) @ConditionalOnMissingBean(name = ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) - public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, - RocketMQMessageConverter rocketMQMessageConverter) { + public RocketMQTemplate rocketMQTemplate(RocketMQMessageConverter rocketMQMessageConverter) { RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); - rocketMQTemplate.setProducer(mqProducer); + if (applicationContext.containsBean(PRODUCER_BEAN_NAME)) { + rocketMQTemplate.setProducer((DefaultMQProducer) applicationContext.getBean(PRODUCER_BEAN_NAME)); + } + if (applicationContext.containsBean(CONSUMER_BEAN_NAME)) { + rocketMQTemplate.setConsumer((DefaultLitePullConsumer) applicationContext.getBean(CONSUMER_BEAN_NAME)); + } rocketMQTemplate.setMessageConverter(rocketMQMessageConverter.getMessageConverter()); return rocketMQTemplate; } + + static class ProducerOrConsumerPropertyCondition extends AnyNestedCondition { + + public ProducerOrConsumerPropertyCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } + + @ConditionalOnBean(DefaultMQProducer.class) + static class DefaultMQProducerExistsCondition { + } + + @ConditionalOnBean(DefaultLitePullConsumer.class) + static class DefaultLitePullConsumerExistsCondition { + } + } } diff --git a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java index c08b3773..98a88f73 100644 --- a/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java +++ b/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java @@ -230,6 +230,47 @@ public void setConsumer(Consumer consumer) { } public static final class Consumer { + /** + * Group name of consumer. + */ + private String group; + + /** + * Topic name of consumer. + */ + private String topic; + + /** + * Control message mode, if you want all subscribers receive message all message, broadcasting is a good choice. + */ + private String messageModel = "CLUSTERING"; + + /** + * Control how to selector message. + * + */ + private String selectorType = "TAG"; + + /** + * Control which message can be select. + */ + private String selectorExpression = "*"; + + /** + * The property of "access-key". + */ + private String accessKey; + + /** + * The property of "secret-key". + */ + private String secretKey; + + /** + * Maximum number of messages pulled each time. + */ + private int pullBatchSize = 10; + /** * listener configuration container * the pattern is like this: @@ -239,6 +280,70 @@ public static final class Consumer { */ private Map> listeners = new HashMap<>(); + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public String getMessageModel() { + return messageModel; + } + + public void setMessageModel(String messageModel) { + this.messageModel = messageModel; + } + + public String getSelectorType() { + return selectorType; + } + + public void setSelectorType(String selectorType) { + this.selectorType = selectorType; + } + + public String getSelectorExpression() { + return selectorExpression; + } + + public void setSelectorExpression(String selectorExpression) { + this.selectorExpression = selectorExpression; + } + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public int getPullBatchSize() { + return pullBatchSize; + } + + public void setPullBatchSize(int pullBatchSize) { + this.pullBatchSize = pullBatchSize; + } + public Map> getListeners() { return listeners; } 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 78f0b2d7..a18e7815 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 @@ -17,15 +17,7 @@ package org.apache.rocketmq.spring.core; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ExecutorService; - +import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.MessageQueueSelector; @@ -52,12 +44,24 @@ import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.MimeTypeUtils; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ExecutorService; + @SuppressWarnings({"WeakerAccess", "unused"}) public class RocketMQTemplate extends AbstractMessageSendingTemplate implements InitializingBean, DisposableBean { private static final Logger log = LoggerFactory.getLogger(RocketMQTemplate.class); private DefaultMQProducer producer; + private DefaultLitePullConsumer consumer; + private String charset = "UTF-8"; private MessageQueueSelector messageQueueSelector = new SelectMessageQueueByHash(); @@ -72,6 +76,14 @@ public void setProducer(DefaultMQProducer producer) { this.producer = producer; } + public DefaultLitePullConsumer getConsumer() { + return consumer; + } + + public void setConsumer(DefaultLitePullConsumer consumer) { + this.consumer = consumer; + } + public String getCharset() { return charset; } @@ -860,6 +872,13 @@ public void afterPropertiesSet() throws Exception { if (producer != null) { producer.start(); } + if (Objects.nonNull(consumer)) { + try { + consumer.start(); + } catch (Exception e) { + log.error("Failed to startup PullConsumer for RocketMQTemplate", e); + } + } } @Override @@ -883,6 +902,9 @@ public void destroy() { if (Objects.nonNull(producer)) { producer.shutdown(); } + if (Objects.nonNull(consumer)) { + consumer.shutdown(); + } } /** @@ -967,4 +989,52 @@ private Type getMessageType(RocketMQLocalRequestCallback rocketMQLocalRequestCal } return Object.class; } + + /** + * receive message in pull mode. + * + * @param clazz message object type + * @param + * @return message list + */ + public List receive(Class clazz) { + return receive(clazz, this.consumer.getPollTimeoutMillis()); + } + + /** + * Same to {@link #receive(Class)} with receive timeout specified in addition. + * + * @param clazz message object type + * @param timeout receive timeout with millis + * @param + * @return message list + */ + public List receive(Class clazz, long timeout) { + List messageExts = this.consumer.poll(timeout); + List list = new ArrayList<>(messageExts.size()); + for (MessageExt messageExt : messageExts) { + list.add(doConvertMessage(messageExt, clazz)); + } + return list; + } + + @SuppressWarnings("unchecked") + private T doConvertMessage(MessageExt messageExt, Class messageType) { + if (Objects.equals(messageType, MessageExt.class)) { + return (T) messageExt; + } else { + String str = new String(messageExt.getBody(), Charset.forName(charset)); + if (Objects.equals(messageType, String.class)) { + return (T) str; + } else { + // If msgType not string, use objectMapper change it. + try { + return (T) this.getMessageConverter().fromMessage(MessageBuilder.withPayload(str).build(), messageType); + } catch (Exception e) { + log.info("convert failed. str:{}, msgType:{}", str, messageType); + throw new RuntimeException("cannot convert message to " + messageType, e); + } + } + } + } } \ No newline at end of file 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 index 082b0f68..a891fa7b 100644 --- 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 @@ -17,12 +17,11 @@ package org.apache.rocketmq.spring.support; import com.fasterxml.jackson.databind.ObjectMapper; -import java.lang.reflect.Field; -import java.nio.charset.Charset; -import java.util.Map; -import java.util.Objects; import org.apache.rocketmq.acl.common.AclClientRPCHook; import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.client.AccessChannel; +import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer; +import org.apache.rocketmq.client.consumer.MessageSelector; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.LocalTransactionState; @@ -36,6 +35,8 @@ import org.apache.rocketmq.common.message.MessageConst; import org.apache.rocketmq.common.message.MessageExt; import org.apache.rocketmq.remoting.RPCHook; +import org.apache.rocketmq.spring.annotation.MessageModel; +import org.apache.rocketmq.spring.annotation.SelectorType; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; import org.slf4j.Logger; @@ -48,6 +49,11 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import java.lang.reflect.Field; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.Objects; + public class RocketMQUtil { private final static Logger log = LoggerFactory.getLogger(RocketMQUtil.class); @@ -285,4 +291,46 @@ public static String getInstanceName(String identify) { return instanceName.toString(); } + public static DefaultLitePullConsumer createDefaultLitePullConsumer(String nameServer, String accessChannel, + String groupName, String topicName, MessageModel messageModel, SelectorType selectorType, + String selectorExpression, String ak, String sk, int pullBatchSize) + throws MQClientException { + DefaultLitePullConsumer litePullConsumer = null; + if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { + litePullConsumer = new DefaultLitePullConsumer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk))); + litePullConsumer.setVipChannelEnabled(false); + } else { + litePullConsumer = new DefaultLitePullConsumer(groupName); + } + litePullConsumer.setNamesrvAddr(nameServer); + litePullConsumer.setInstanceName(RocketMQUtil.getInstanceName(nameServer)); + litePullConsumer.setPullBatchSize(pullBatchSize); + if (accessChannel != null) { + litePullConsumer.setAccessChannel(AccessChannel.valueOf(accessChannel)); + } + + switch (messageModel) { + case BROADCASTING: + litePullConsumer.setMessageModel(org.apache.rocketmq.common.protocol.heartbeat.MessageModel.BROADCASTING); + break; + case CLUSTERING: + litePullConsumer.setMessageModel(org.apache.rocketmq.common.protocol.heartbeat.MessageModel.CLUSTERING); + break; + default: + throw new IllegalArgumentException("Property 'messageModel' was wrong."); + } + + switch (selectorType) { + case SQL92: + litePullConsumer.subscribe(topicName, MessageSelector.bySql(selectorExpression)); + break; + case TAG: + litePullConsumer.subscribe(topicName, selectorExpression); + break; + default: + throw new IllegalArgumentException("Property 'selectorType' was wrong."); + } + + return litePullConsumer; + } } diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java index 514c138c..9f31b09b 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -19,8 +19,11 @@ import java.util.ArrayList; import java.util.List; + +import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer; import org.apache.rocketmq.client.producer.DefaultMQProducer; import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.spring.annotation.ExtRocketMQConsumerConfiguration; import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; @@ -52,6 +55,12 @@ public void testDefaultMQProducerNotCreatedByDefault() { runner.run(context -> context.getBean(DefaultMQProducer.class)); } + @Test(expected = NoSuchBeanDefinitionException.class) + public void testDefaultLitePullConsumerNotCreatedByDefault() { + // You will see the WARN log message about missing rocketmq.name-server spring property when running this test case. + runner.run(context -> context.getBean(DefaultLitePullConsumer.class)); + } + @Test public void testDefaultMQProducerWithRelaxPropertyName() { runner.withPropertyValues("rocketmq.nameServer=127.0.0.1:9876", @@ -64,6 +73,19 @@ public void testDefaultMQProducerWithRelaxPropertyName() { } + @Test + public void testDefaultLitePullConsumerWithRelaxPropertyName() { + runner.withPropertyValues("rocketmq.nameServer=127.0.0.1:9876", + "rocketmq.consumer.group=spring_rocketmq", + "rocketmq.consumer.topic=test", + "rocketmq.accessChannel=LOCAL"). + run((context) -> { + assertThat(context).hasSingleBean(DefaultLitePullConsumer.class); + assertThat(context).hasSingleBean(RocketMQProperties.class); + }); + + } + @Test public void testBadAccessChannelProperty() { runner.withPropertyValues("rocketmq.nameServer=127.0.0.1:9876", @@ -73,6 +95,15 @@ public void testBadAccessChannelProperty() { //Should throw exception for bad accessChannel property assertThat(context).getFailure(); }); + + runner.withPropertyValues("rocketmq.nameServer=127.0.0.1:9876", + "rocketmq.consumer.group=spring_rocketmq", + "rocketmq.consumer.topic=test", + "rocketmq.accessChannel=LOCAL123"). + run((context) -> { + //Should throw exception for bad accessChannel property + assertThat(context).getFailure(); + }); } @Test @@ -84,6 +115,16 @@ public void testDefaultMQProducer() { }); } + @Test + public void testDefaultLitePullConsumer() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", + "rocketmq.consumer.group=spring_rocketmq", + "rocketmq.consumer.topic=test"). + run((context) -> { + assertThat(context).hasSingleBean(DefaultLitePullConsumer.class); + }); + } + @Test public void testExtRocketMQTemplate() { runner.withPropertyValues("rocketmq.name-server=127.0.1.1:9876"). @@ -95,6 +136,16 @@ public void testExtRocketMQTemplate() { }); } + + @Test + public void testExtRocketMQConsumer() { + runner.withPropertyValues("rocketmq.name-server=127.0.1.1:9876"). + withUserConfiguration(TestExtRocketMQConsumerConfig.class, CustomObjectMappersConfig.class). + run((context) -> { + assertThat(context).getBean("extRocketMQTemplate").hasFieldOrProperty("consumer"); + }); + } + @Test public void testConsumerListener() { runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", @@ -347,5 +398,20 @@ public void onMessage(Object message) { } } + + @Configuration + static class TestExtRocketMQConsumerConfig { + + @Bean + public RocketMQTemplate extRocketMQTemplate() { + return new TestExtRocketMQConsumer(); + } + + } + + @ExtRocketMQConsumerConfiguration(topic = "test", group = "test", nameServer = "127.0.0.1:9876") + static class TestExtRocketMQConsumer extends RocketMQTemplate { + + } } diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/ExtRocketMQTemplateTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/ExtRocketMQTemplateTest.java index 7430ff54..dc88253a 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/ExtRocketMQTemplateTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/ExtRocketMQTemplateTest.java @@ -16,8 +16,8 @@ */ package org.apache.rocketmq.spring.core; -import javax.annotation.Resource; import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.spring.annotation.ExtRocketMQConsumerConfiguration; import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration; @@ -29,17 +29,22 @@ import org.springframework.messaging.support.MessageBuilder; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import javax.annotation.Resource; + import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(properties = { - "rocketmq.nameServer=127.0.0.1:9876", "rocketmq.producer.group=extRocketMQTemplate-test-producer_group"}, classes = {RocketMQAutoConfiguration.class, ExtRocketMQTemplate.class, ExtTransactionListenerImpl.class}) + "rocketmq.nameServer=127.0.0.1:9876", "rocketmq.producer.group=extRocketMQTemplate-test-producer_group"}, classes = {RocketMQAutoConfiguration.class, ExtRocketMQTemplate.class, ExtTransactionListenerImpl.class, ExtRocketMQConsumer.class}) public class ExtRocketMQTemplateTest { @Resource(name = "extRocketMQTemplate") private RocketMQTemplate extRocketMQTemplate; + @Resource(name = "extRocketMQConsumer") + private ExtRocketMQConsumer extRocketMQConsumer; + @Resource private RocketMQTemplate rocketMQTemplate; @@ -49,6 +54,10 @@ public void testProperties() { assertThat(extRocketMQTemplate.getProducer().getProducerGroup()).isEqualTo("extRocketMQTemplate-test-group"); assertThat(extRocketMQTemplate.getProducer().getSendMsgTimeout()).isEqualTo(3000); assertThat(extRocketMQTemplate.getProducer().getMaxMessageSize()).isEqualTo(4 * 1024); + + assertThat(extRocketMQConsumer.getConsumer().getNamesrvAddr()).isEqualTo("172.0.0.1:9876"); + assertThat(extRocketMQConsumer.getConsumer().getConsumerGroup()).isEqualTo("extRocketMQTemplate-test-group"); + assertThat(extRocketMQConsumer.getConsumer().getPullBatchSize()).isEqualTo(3); } @Test @@ -93,6 +102,11 @@ public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { } } +@ExtRocketMQConsumerConfiguration(nameServer = "172.0.0.1:9876", group = "extRocketMQTemplate-test-group", topic = "test", pullBatchSize = 3) +class ExtRocketMQConsumer extends RocketMQTemplate { + +} + diff --git a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java index 56a7de62..2103da2d 100644 --- a/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java +++ b/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/core/RocketMQTemplateTest.java @@ -50,7 +50,8 @@ "test.rocketmq.topic=test", "rocketmq.producer.access-key=test-ak", "rocketmq.producer.secret-key=test-sk", "rocketmq.accessChannel=LOCAL", "rocketmq.producer.sendMessageTimeout= 3500", "rocketmq.producer.retryTimesWhenSendFailed=3", - "rocketmq.producer.retryTimesWhenSendAsyncFailed=3"}, classes = {RocketMQAutoConfiguration.class, TransactionListenerImpl.class}) + "rocketmq.producer.retryTimesWhenSendAsyncFailed=3", + "rocketmq.consumer.group=spring_rocketmq", "rocketmq.consumer.topic=test"}, classes = {RocketMQAutoConfiguration.class, TransactionListenerImpl.class}) public class RocketMQTemplateTest { @Resource @@ -94,6 +95,15 @@ public void testSendMessage() { } } + @Test + public void testReceiveMessage() { + try { + rocketMQTemplate.receive(String.class); + } catch (MessagingException e) { + assertThat(e).hasMessageContaining("org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to [127.0.0.1:9876] failed"); + } + } + @Test public void testSendMessage_withCustomAsyncSenderExecutor() { ExecutorService executorService = new ThreadPoolExecutor( @@ -234,6 +244,10 @@ public void testProperties() { assertThat(rocketMQTemplate.getProducer().getRetryTimesWhenSendAsyncFailed()).isEqualTo(3); assertThat(rocketMQTemplate.getProducer().getRetryTimesWhenSendFailed()).isEqualTo(3); assertThat(rocketMQTemplate.getProducer().getCompressMsgBodyOverHowmuch()).isEqualTo(1024 * 4); + + assertThat(rocketMQTemplate.getConsumer().getNamesrvAddr()).isEqualTo("127.0.0.1:9876"); + assertThat(rocketMQTemplate.getConsumer().getConsumerGroup()).isEqualTo("spring_rocketmq"); + assertThat(rocketMQTemplate.getConsumer().getAccessChannel()).isEqualTo(AccessChannel.LOCAL); } @Test From 4efcf71fbb51f31255943d9a5b640c1d2030d415 Mon Sep 17 00:00:00 2001 From: wz2cool Date: Wed, 23 Dec 2020 13:58:43 +0800 Subject: [PATCH 101/105] [ISSUE #327] Remove info log in consumeMessage method --- .../spring/support/DefaultRocketMQListenerContainer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 952b4e1f..0b513a3f 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 @@ -376,7 +376,7 @@ public ConsumeOrderlyStatus consumeMessage(List msgs, ConsumeOrderly long now = System.currentTimeMillis(); handleMessage(messageExt); long costTime = System.currentTimeMillis() - now; - log.info("consume {} cost: {} ms", messageExt.getMsgId(), costTime); + log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime); } catch (Exception e) { log.warn("consume message failed. messageId:{}, topic:{}, reconsumeTimes:{}", messageExt.getMsgId(), messageExt.getTopic(), messageExt.getReconsumeTimes(), e); context.setSuspendCurrentQueueTimeMillis(suspendCurrentQueueTimeMillis); @@ -402,7 +402,7 @@ private void handleMessage( if (sendResult.getSendStatus() != SendStatus.SEND_OK) { log.error("Consumer replies message failed. SendStatus: {}", sendResult.getSendStatus()); } else { - log.info("Consumer replies message success."); + log.debug("Consumer replies message success."); } } From 442cd8b4e35f99f836c7c7a987b6574761cf336a Mon Sep 17 00:00:00 2001 From: rongtong Date: Mon, 4 Jan 2021 14:37:33 +0800 Subject: [PATCH 102/105] [ISSUE# 329] Upgrade RocketMQ version (#330) * chore(version): update rocketmq version * chore(version): update rocketmq-spring-boot-starter-version in samples --- rocketmq-spring-boot-parent/pom.xml | 6 +++--- rocketmq-spring-boot-samples/pom.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index f0d7b1dd..804dc53e 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -40,7 +40,7 @@ 2.1.2-SNAPSHOT - 4.7.1 + 4.8.0 1.7.25 2.11.1 1.2.72 @@ -112,7 +112,7 @@ org.apache.rocketmq rocketmq-client - ${rocketmq-version} + ${rocketmq.version} org.slf4j @@ -124,7 +124,7 @@ org.apache.rocketmq rocketmq-acl - ${rocketmq-version} + ${rocketmq.version} diff --git a/rocketmq-spring-boot-samples/pom.xml b/rocketmq-spring-boot-samples/pom.xml index 3d8978c6..e582ab14 100644 --- a/rocketmq-spring-boot-samples/pom.xml +++ b/rocketmq-spring-boot-samples/pom.xml @@ -40,7 +40,7 @@ 1.8 1.8 - 2.1.0 + 2.1.2-SNAPSHOT From d5138af7c78d07abf01be5ecb814b5dbb78c875f Mon Sep 17 00:00:00 2001 From: rongtong Date: Mon, 4 Jan 2021 14:40:13 +0800 Subject: [PATCH 103/105] doc(readme¬ice):update notice year and update readme document (#332) --- NOTICE | 2 +- README.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NOTICE b/NOTICE index 65ebdd03..086ee9fa 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache RocketMQ -Copyright 2016-2020 The Apache Software Foundation +Copyright 2016-2021 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 cb593dc3..5e2594e0 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ This project aims to help developers quickly integrate [RocketMQ](http://rocketm - [x] Support message tracing - [x] Support authentication and authorization - [x] Support request-reply message exchange pattern +- [x] Consume messages with push/pull mode ## Prerequisites - JDK 1.8 and above From 66a6d8b51c6202b14195b1ac1a4311a7ce3e81dc Mon Sep 17 00:00:00 2001 From: RongtongJin <794220751@qq.com> Date: Fri, 8 Jan 2021 15:04:57 +0800 Subject: [PATCH 104/105] [maven-release-plugin] prepare release rocketmq-spring-all-2.2.0 --- pom.xml | 4 ++-- rocketmq-spring-boot-parent/pom.xml | 4 ++-- rocketmq-spring-boot-starter/pom.xml | 2 +- rocketmq-spring-boot/pom.xml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 5b998825..9764cb37 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.1.2-SNAPSHOT + 2.2.0 pom Apache RocketMQ Spring Boot ${project.version} @@ -39,7 +39,7 @@ git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git - HEAD + rocketmq-spring-all-2.2.0 diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index 804dc53e..d0651b9a 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.1.2-SNAPSHOT + 2.2.0 ../pom.xml @@ -38,7 +38,7 @@ 2.0.5.RELEASE 5.1.0.RELEASE - 2.1.2-SNAPSHOT + 2.2.0 4.8.0 1.7.25 diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml index c0e6b8a3..42f60872 100644 --- a/rocketmq-spring-boot-starter/pom.xml +++ b/rocketmq-spring-boot-starter/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.1.2-SNAPSHOT + 2.2.0 ../rocketmq-spring-boot-parent/pom.xml diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml index 9627b14b..7a661804 100644 --- a/rocketmq-spring-boot/pom.xml +++ b/rocketmq-spring-boot/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.1.2-SNAPSHOT + 2.2.0 ../rocketmq-spring-boot-parent/pom.xml From 7ac9e6e66877d66c225f2fc6b50f8a5a4157e8e1 Mon Sep 17 00:00:00 2001 From: RongtongJin <794220751@qq.com> Date: Fri, 8 Jan 2021 15:05:20 +0800 Subject: [PATCH 105/105] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- rocketmq-spring-boot-parent/pom.xml | 4 ++-- rocketmq-spring-boot-starter/pom.xml | 2 +- rocketmq-spring-boot/pom.xml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 9764cb37..7e7ecce5 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.2.0 + 2.2.1-SNAPSHOT pom Apache RocketMQ Spring Boot ${project.version} @@ -39,7 +39,7 @@ git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git scm:git:git@github.com:apache/rocketmq-spring.git - rocketmq-spring-all-2.2.0 + HEAD diff --git a/rocketmq-spring-boot-parent/pom.xml b/rocketmq-spring-boot-parent/pom.xml index d0651b9a..12e08076 100644 --- a/rocketmq-spring-boot-parent/pom.xml +++ b/rocketmq-spring-boot-parent/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-all - 2.2.0 + 2.2.1-SNAPSHOT ../pom.xml @@ -38,7 +38,7 @@ 2.0.5.RELEASE 5.1.0.RELEASE - 2.2.0 + 2.2.1-SNAPSHOT 4.8.0 1.7.25 diff --git a/rocketmq-spring-boot-starter/pom.xml b/rocketmq-spring-boot-starter/pom.xml index 42f60872..370d2262 100644 --- a/rocketmq-spring-boot-starter/pom.xml +++ b/rocketmq-spring-boot-starter/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.2.0 + 2.2.1-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml diff --git a/rocketmq-spring-boot/pom.xml b/rocketmq-spring-boot/pom.xml index 7a661804..3426246b 100644 --- a/rocketmq-spring-boot/pom.xml +++ b/rocketmq-spring-boot/pom.xml @@ -22,7 +22,7 @@ org.apache.rocketmq rocketmq-spring-boot-parent - 2.2.0 + 2.2.1-SNAPSHOT ../rocketmq-spring-boot-parent/pom.xml