From cbd64061cecc394a9467a7c98b4dd52c1f4c2061 Mon Sep 17 00:00:00 2001
From: zkzlx
Date: Mon, 1 Feb 2021 11:23:10 +0800
Subject: [PATCH 01/19] Code refactoring and some new feature support
---
pom.xml | 15 +-
.../pom.xml | 7 +-
.../binder/rocketmq/RocketMQBinderUtils.java | 89 --
.../RocketMQMessageChannelBinder.java | 295 ++----
.../RocketMQBinderHealthIndicator.java | 10 +-
.../RocketMQListenerBindingContainer.java | 935 +++++++++---------
.../RocketMQInboundChannelAdapter.java | 176 ----
.../integration/RocketMQMessageHandler.java | 302 ------
.../integration/RocketMQMessageSource.java | 382 -------
.../rocketmq/metrics/Instrumentation.java | 21 +
.../metrics/InstrumentationManager.java | 35 +-
...RocketMQBinderConfigurationProperties.java | 81 +-
.../properties/RocketMQBindingProperties.java | 49 -
.../RocketMQConsumerProperties.java | 429 ++++++--
.../RocketMQExtendedBindingProperties.java | 12 +-
.../RocketMQProducerProperties.java | 201 ++--
.../PartitionMessageQueueSelector.java | 2 +-
17 files changed, 1111 insertions(+), 1930 deletions(-)
delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java
delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQInboundChannelAdapter.java
delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageHandler.java
delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQMessageSource.java
delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBindingProperties.java
diff --git a/pom.xml b/pom.xml
index 7f9f0f88b8..3fd389aca0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -98,6 +98,7 @@
4.0.1
+ 4.6.12.0.2
@@ -258,10 +259,20 @@
+
+
+
+
+
org.apache.rocketmq
- rocketmq-spring-boot-starter
- ${rocketmq.starter.version}
+ rocketmq-client
+ ${rocketmq.version}
+
+
+ org.apache.rocketmq
+ rocketmq-acl
+ ${rocketmq.version}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml
index ec44c9d7a4..ca5c223917 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/pom.xml
@@ -50,9 +50,12 @@
org.apache.rocketmq
- rocketmq-spring-boot-starter
+ rocketmq-client
+
+
+ org.apache.rocketmq
+ rocketmq-acl
-
org.springframework.bootspring-boot-starter-test
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java
deleted file mode 100644
index c7daff0efb..0000000000
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderUtils.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2013-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://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 com.alibaba.cloud.stream.binder.rocketmq;
-
-import java.util.Arrays;
-import java.util.List;
-
-import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;
-import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties;
-
-import org.springframework.util.CollectionUtils;
-import org.springframework.util.StringUtils;
-
-/**
- * @author Jim
- */
-public final class RocketMQBinderUtils {
-
- private RocketMQBinderUtils() {
-
- }
-
- public static RocketMQBinderConfigurationProperties mergeProperties(
- RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties,
- RocketMQProperties rocketMQProperties) {
- RocketMQBinderConfigurationProperties result = new RocketMQBinderConfigurationProperties();
- if (StringUtils.isEmpty(rocketMQProperties.getNameServer())) {
- result.setNameServer(rocketBinderConfigurationProperties.getNameServer());
- }
- else {
- result.setNameServer(
- Arrays.asList(rocketMQProperties.getNameServer().split(";")));
- }
- if (rocketMQProperties.getProducer() == null
- || StringUtils.isEmpty(rocketMQProperties.getProducer().getAccessKey())) {
- result.setAccessKey(rocketBinderConfigurationProperties.getAccessKey());
- }
- else {
- result.setAccessKey(rocketMQProperties.getProducer().getAccessKey());
- }
- if (rocketMQProperties.getProducer() == null
- || StringUtils.isEmpty(rocketMQProperties.getProducer().getSecretKey())) {
- result.setSecretKey(rocketBinderConfigurationProperties.getSecretKey());
- }
- else {
- result.setSecretKey(rocketMQProperties.getProducer().getSecretKey());
- }
- if (rocketMQProperties.getProducer() == null || StringUtils
- .isEmpty(rocketMQProperties.getProducer().getCustomizedTraceTopic())) {
- result.setCustomizedTraceTopic(
- rocketBinderConfigurationProperties.getCustomizedTraceTopic());
- }
- else {
- result.setCustomizedTraceTopic(
- rocketMQProperties.getProducer().getCustomizedTraceTopic());
- }
- if (rocketMQProperties.getProducer() != null
- && rocketMQProperties.getProducer().isEnableMsgTrace()) {
- result.setEnableMsgTrace(Boolean.TRUE);
- }
- else {
- result.setEnableMsgTrace(
- rocketBinderConfigurationProperties.isEnableMsgTrace());
- }
- return result;
- }
-
- public static String getNameServerStr(List nameServerList) {
- if (CollectionUtils.isEmpty(nameServerList)) {
- return null;
- }
- return String.join(";", nameServerList);
- }
-
-}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java
index e5a2e24b1d..5683bff68e 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2013-2018 the original author or authors.
+ * Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * https://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,34 +16,18 @@
package com.alibaba.cloud.stream.binder.rocketmq;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import com.alibaba.cloud.stream.binder.rocketmq.consuming.RocketMQListenerBindingContainer;
-import com.alibaba.cloud.stream.binder.rocketmq.integration.RocketMQInboundChannelAdapter;
-import com.alibaba.cloud.stream.binder.rocketmq.integration.RocketMQMessageHandler;
-import com.alibaba.cloud.stream.binder.rocketmq.integration.RocketMQMessageSource;
-import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager;
+import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache;
+import com.alibaba.cloud.stream.binder.rocketmq.extend.ErrorAcknowledgeHandler;
+import com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.RocketMQInboundChannelAdapter;
+import com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull.DefaultErrorAcknowledgeHandler;
+import com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull.RocketMQMessageSource;
+import com.alibaba.cloud.stream.binder.rocketmq.integration.outbound.RocketMQProducerMessageHandler;
import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;
import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;
import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties;
import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties;
import com.alibaba.cloud.stream.binder.rocketmq.provisioning.RocketMQTopicProvisioner;
-import com.alibaba.cloud.stream.binder.rocketmq.provisioning.selector.PartitionMessageQueueSelector;
-import com.alibaba.cloud.stream.binder.rocketmq.support.JacksonRocketMQHeaderMapper;
-import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.rocketmq.acl.common.AclClientRPCHook;
-import org.apache.rocketmq.acl.common.SessionCredentials;
-import org.apache.rocketmq.client.producer.DefaultMQProducer;
-import org.apache.rocketmq.common.UtilAll;
-import org.apache.rocketmq.remoting.RPCHook;
-import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties;
-import org.apache.rocketmq.spring.core.RocketMQTemplate;
-import org.apache.rocketmq.spring.support.RocketMQUtil;
+import com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils;
import org.springframework.cloud.stream.binder.AbstractMessageChannelBinder;
import org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider;
@@ -55,15 +39,19 @@
import org.springframework.cloud.stream.provisioning.ProducerDestination;
import org.springframework.integration.StaticMessageHeaderAccessor;
import org.springframework.integration.acks.AcknowledgmentCallback;
-import org.springframework.integration.acks.AcknowledgmentCallback.Status;
import org.springframework.integration.channel.AbstractMessageChannel;
import org.springframework.integration.core.MessageProducer;
+import org.springframework.integration.support.DefaultErrorMessageStrategy;
+import org.springframework.integration.support.ErrorMessageStrategy;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
import org.springframework.util.StringUtils;
/**
+ * A {@link org.springframework.cloud.stream.binder.Binder} that uses RocketMQ as the
+ * underlying middleware.
+ *
* @author Jim
*/
public class RocketMQMessageChannelBinder extends
@@ -71,120 +59,44 @@ public class RocketMQMessageChannelBinder extends
implements
ExtendedPropertiesBinder {
- private RocketMQExtendedBindingProperties extendedBindingProperties = new RocketMQExtendedBindingProperties();
-
- private final RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties;
-
- private final RocketMQProperties rocketMQProperties;
-
- private final InstrumentationManager instrumentationManager;
-
- private Map topicInUse = new HashMap<>();
+ private final RocketMQExtendedBindingProperties extendedBindingProperties;
+ private final RocketMQBinderConfigurationProperties binderConfigurationProperties;
- public RocketMQMessageChannelBinder(RocketMQTopicProvisioner provisioningProvider,
+ public RocketMQMessageChannelBinder(
+ RocketMQBinderConfigurationProperties binderConfigurationProperties,
RocketMQExtendedBindingProperties extendedBindingProperties,
- RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties,
- RocketMQProperties rocketMQProperties,
- InstrumentationManager instrumentationManager) {
- super(null, provisioningProvider);
+ RocketMQTopicProvisioner provisioningProvider) {
+ super(new String[0], provisioningProvider);
this.extendedBindingProperties = extendedBindingProperties;
- this.rocketBinderConfigurationProperties = rocketBinderConfigurationProperties;
- this.rocketMQProperties = rocketMQProperties;
- this.instrumentationManager = instrumentationManager;
+ this.binderConfigurationProperties = binderConfigurationProperties;
}
@Override
protected MessageHandler createProducerMessageHandler(ProducerDestination destination,
- ExtendedProducerProperties producerProperties,
+ ExtendedProducerProperties extendedProducerProperties,
MessageChannel channel, MessageChannel errorChannel) throws Exception {
- if (producerProperties.getExtension().getEnabled()) {
-
- // if producerGroup is empty, using destination
- String extendedProducerGroup = producerProperties.getExtension().getGroup();
- String producerGroup = StringUtils.isEmpty(extendedProducerGroup)
- ? destination.getName() : extendedProducerGroup;
-
- RocketMQBinderConfigurationProperties mergedProperties = RocketMQBinderUtils
- .mergeProperties(rocketBinderConfigurationProperties,
- rocketMQProperties);
-
- RocketMQTemplate rocketMQTemplate;
- if (producerProperties.getExtension().getTransactional()) {
- Map rocketMQTemplates = getBeanFactory()
- .getBeansOfType(RocketMQTemplate.class);
- if (rocketMQTemplates.size() == 0) {
- throw new IllegalStateException(
- "there is no RocketMQTemplate in Spring BeanFactory");
- }
- else if (rocketMQTemplates.size() > 1) {
- throw new IllegalStateException(
- "there is more than 1 RocketMQTemplates in Spring BeanFactory");
- }
- rocketMQTemplate = rocketMQTemplates.values().iterator().next();
- }
- else {
- rocketMQTemplate = new RocketMQTemplate();
- rocketMQTemplate.setObjectMapper(this.getApplicationContext()
- .getBeansOfType(ObjectMapper.class).values().iterator().next());
- DefaultMQProducer producer;
- String ak = mergedProperties.getAccessKey();
- String sk = mergedProperties.getSecretKey();
- if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) {
- RPCHook rpcHook = new AclClientRPCHook(
- new SessionCredentials(ak, sk));
- producer = new DefaultMQProducer(producerGroup, rpcHook,
- mergedProperties.isEnableMsgTrace(),
- mergedProperties.getCustomizedTraceTopic());
- producer.setVipChannelEnabled(false);
- producer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook,
- destination.getName() + "|" + UtilAll.getPid()));
- }
- else {
- producer = new DefaultMQProducer(producerGroup);
- producer.setVipChannelEnabled(
- producerProperties.getExtension().getVipChannelEnabled());
- }
- producer.setNamesrvAddr(RocketMQBinderUtils
- .getNameServerStr(mergedProperties.getNameServer()));
- producer.setSendMsgTimeout(
- producerProperties.getExtension().getSendMessageTimeout());
- producer.setRetryTimesWhenSendFailed(
- producerProperties.getExtension().getRetryTimesWhenSendFailed());
- producer.setRetryTimesWhenSendAsyncFailed(producerProperties
- .getExtension().getRetryTimesWhenSendAsyncFailed());
- producer.setCompressMsgBodyOverHowmuch(producerProperties.getExtension()
- .getCompressMessageBodyThreshold());
- producer.setRetryAnotherBrokerWhenNotStoreOK(
- producerProperties.getExtension().isRetryNextServer());
- producer.setMaxMessageSize(
- producerProperties.getExtension().getMaxMessageSize());
- rocketMQTemplate.setProducer(producer);
- if (producerProperties.isPartitioned()) {
- rocketMQTemplate
- .setMessageQueueSelector(new PartitionMessageQueueSelector());
- }
- }
-
- RocketMQMessageHandler messageHandler = new RocketMQMessageHandler(
- rocketMQTemplate, destination.getName(), producerGroup,
- producerProperties.getExtension().getTransactional(),
- instrumentationManager, producerProperties,
- ((AbstractMessageChannel) channel).getInterceptors().stream().filter(
- channelInterceptor -> channelInterceptor instanceof MessageConverterConfigurer.PartitioningInterceptor)
- .map(channelInterceptor -> ((MessageConverterConfigurer.PartitioningInterceptor) channelInterceptor))
- .findFirst().orElse(null));
- messageHandler.setBeanFactory(this.getApplicationContext().getBeanFactory());
- messageHandler.setSync(producerProperties.getExtension().getSync());
- messageHandler.setHeaderMapper(createHeaderMapper(producerProperties));
- if (errorChannel != null) {
- messageHandler.setSendFailureChannel(errorChannel);
- }
- return messageHandler;
- }
- else {
+ if (!extendedProducerProperties.getExtension().getEnabled()) {
throw new RuntimeException("Binding for channel " + destination.getName()
+ " has been disabled, message can't be delivered");
}
+ RocketMQProducerProperties mqProducerProperties = RocketMQUtils
+ .mergeRocketMQProperties(binderConfigurationProperties,
+ extendedProducerProperties.getExtension());
+ RocketMQProducerMessageHandler messageHandler = new RocketMQProducerMessageHandler(
+ destination, extendedProducerProperties, mqProducerProperties);
+ messageHandler.setApplicationContext(this.getApplicationContext());
+ if (errorChannel != null) {
+ messageHandler.setSendFailureChannel(errorChannel);
+ }
+ MessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor = ((AbstractMessageChannel) channel)
+ .getInterceptors().stream()
+ .filter(channelInterceptor -> channelInterceptor instanceof MessageConverterConfigurer.PartitioningInterceptor)
+ .map(channelInterceptor -> ((MessageConverterConfigurer.PartitioningInterceptor) channelInterceptor))
+ .findFirst().orElse(null);
+ messageHandler.setPartitioningInterceptor(partitioningInterceptor);
+ messageHandler.setBeanFactory(this.getApplicationContext().getBeanFactory());
+ messageHandler.setErrorMessageStrategy(this.getErrorMessageStrategy());
+ return messageHandler;
}
@Override
@@ -198,56 +110,43 @@ protected MessageHandler createProducerMessageHandler(ProducerDestination destin
@Override
protected MessageProducer createConsumerEndpoint(ConsumerDestination destination,
String group,
- ExtendedConsumerProperties consumerProperties)
+ ExtendedConsumerProperties extendedConsumerProperties)
throws Exception {
- if (group == null || "".equals(group)) {
+ // todo support anymous consumer
+ if (StringUtils.isEmpty(group)) {
throw new RuntimeException(
"'group must be configured for channel " + destination.getName());
}
+ RocketMQUtils.mergeRocketMQProperties(binderConfigurationProperties,
+ extendedConsumerProperties.getExtension());
+ extendedConsumerProperties.getExtension().setGroup(group);
- RocketMQListenerBindingContainer listenerContainer = new RocketMQListenerBindingContainer(
- consumerProperties, rocketBinderConfigurationProperties, this);
- listenerContainer.setConsumerGroup(group);
- listenerContainer.setTopic(destination.getName());
- listenerContainer.setConsumeThreadMax(consumerProperties.getConcurrency());
- listenerContainer.setSuspendCurrentQueueTimeMillis(
- consumerProperties.getExtension().getSuspendCurrentQueueTimeMillis());
- listenerContainer.setDelayLevelWhenNextConsume(
- consumerProperties.getExtension().getDelayLevelWhenNextConsume());
- listenerContainer
- .setNameServer(rocketBinderConfigurationProperties.getNameServer());
- listenerContainer.setHeaderMapper(createHeaderMapper(consumerProperties));
-
- RocketMQInboundChannelAdapter rocketInboundChannelAdapter = new RocketMQInboundChannelAdapter(
- listenerContainer, consumerProperties, instrumentationManager);
-
- topicInUse.put(destination.getName(), group);
-
+ RocketMQInboundChannelAdapter inboundChannelAdapter = new RocketMQInboundChannelAdapter(
+ destination.getName(), extendedConsumerProperties);
ErrorInfrastructure errorInfrastructure = registerErrorInfrastructure(destination,
- group, consumerProperties);
- if (consumerProperties.getMaxAttempts() > 1) {
- rocketInboundChannelAdapter
- .setRetryTemplate(buildRetryTemplate(consumerProperties));
- rocketInboundChannelAdapter
- .setRecoveryCallback(errorInfrastructure.getRecoverer());
+ group, extendedConsumerProperties);
+ if (extendedConsumerProperties.getMaxAttempts() > 1) {
+ inboundChannelAdapter
+ .setRetryTemplate(buildRetryTemplate(extendedConsumerProperties));
+ inboundChannelAdapter.setRecoveryCallback(errorInfrastructure.getRecoverer());
}
else {
- rocketInboundChannelAdapter
- .setErrorChannel(errorInfrastructure.getErrorChannel());
+ inboundChannelAdapter.setErrorChannel(errorInfrastructure.getErrorChannel());
}
-
- return rocketInboundChannelAdapter;
+ return inboundChannelAdapter;
}
@Override
protected PolledConsumerResources createPolledConsumerResources(String name,
String group, ConsumerDestination destination,
- ExtendedConsumerProperties consumerProperties) {
- RocketMQMessageSource rocketMQMessageSource = new RocketMQMessageSource(
- rocketBinderConfigurationProperties, consumerProperties, name, group);
- return new PolledConsumerResources(rocketMQMessageSource,
- registerErrorInfrastructure(destination, group, consumerProperties,
- true));
+ ExtendedConsumerProperties extendedConsumerProperties) {
+ RocketMQUtils.mergeRocketMQProperties(binderConfigurationProperties,
+ extendedConsumerProperties.getExtension());
+ extendedConsumerProperties.getExtension().setGroup(group);
+ RocketMQMessageSource messageSource = new RocketMQMessageSource(name,
+ extendedConsumerProperties);
+ return new PolledConsumerResources(messageSource, registerErrorInfrastructure(
+ destination, group, extendedConsumerProperties, true));
}
@Override
@@ -261,67 +160,47 @@ protected MessageHandler getPolledConsumerErrorMessageHandler(
((MessagingException) message.getPayload())
.getFailedMessage());
if (ack != null) {
- if (properties.getExtension().shouldRequeue()) {
- ack.acknowledge(Status.REQUEUE);
- }
- else {
- ack.acknowledge(Status.REJECT);
- }
+ ErrorAcknowledgeHandler handler = RocketMQBeanContainerCache.getBean(
+ properties.getExtension().getPull().getErrAcknowledge(),
+ ErrorAcknowledgeHandler.class,
+ new DefaultErrorAcknowledgeHandler());
+ ack.acknowledge(
+ handler.handler(((MessagingException) message.getPayload())
+ .getFailedMessage()));
}
}
};
}
+ /**
+ * Binders can return an {@link ErrorMessageStrategy} for building error messages;
+ * binder implementations typically might add extra headers to the error message.
+ *
+ * @return the implementation - may be null.
+ */
@Override
- public RocketMQConsumerProperties getExtendedConsumerProperties(String channelName) {
- return extendedBindingProperties.getExtendedConsumerProperties(channelName);
+ protected ErrorMessageStrategy getErrorMessageStrategy() {
+ // It can be extended to custom if necessary.
+ return new DefaultErrorMessageStrategy();
}
@Override
- public RocketMQProducerProperties getExtendedProducerProperties(String channelName) {
- return extendedBindingProperties.getExtendedProducerProperties(channelName);
+ public RocketMQConsumerProperties getExtendedConsumerProperties(String channelName) {
+ return this.extendedBindingProperties.getExtendedConsumerProperties(channelName);
}
- public Map getTopicInUse() {
- return topicInUse;
+ @Override
+ public RocketMQProducerProperties getExtendedProducerProperties(String channelName) {
+ return this.extendedBindingProperties.getExtendedProducerProperties(channelName);
}
@Override
public String getDefaultsPrefix() {
- return extendedBindingProperties.getDefaultsPrefix();
+ return this.extendedBindingProperties.getDefaultsPrefix();
}
@Override
public Class extends BinderSpecificPropertiesProvider> getExtendedPropertiesEntryClass() {
- return extendedBindingProperties.getExtendedPropertiesEntryClass();
+ return this.extendedBindingProperties.getExtendedPropertiesEntryClass();
}
-
- public void setExtendedBindingProperties(
- RocketMQExtendedBindingProperties extendedBindingProperties) {
- this.extendedBindingProperties = extendedBindingProperties;
- }
-
- private RocketMQHeaderMapper createHeaderMapper(
- final ExtendedConsumerProperties extendedConsumerProperties) {
- Set trustedPackages = extendedConsumerProperties.getExtension()
- .getTrustedPackages();
- return createHeaderMapper(trustedPackages);
- }
-
- private RocketMQHeaderMapper createHeaderMapper(
- final ExtendedProducerProperties producerProperties) {
- return createHeaderMapper(Collections.emptyList());
- }
-
- private RocketMQHeaderMapper createHeaderMapper(Collection trustedPackages) {
- ObjectMapper objectMapper = this.getApplicationContext()
- .getBeansOfType(ObjectMapper.class).values().iterator().next();
- JacksonRocketMQHeaderMapper headerMapper = new JacksonRocketMQHeaderMapper(
- objectMapper);
- if (!StringUtils.isEmpty(trustedPackages)) {
- headerMapper.addTrustedPackages(trustedPackages);
- }
- return headerMapper;
- }
-
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/actuator/RocketMQBinderHealthIndicator.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/actuator/RocketMQBinderHealthIndicator.java
index 1c49359ea9..6e704250a4 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/actuator/RocketMQBinderHealthIndicator.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/actuator/RocketMQBinderHealthIndicator.java
@@ -19,7 +19,6 @@
import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation;
import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
@@ -29,23 +28,20 @@
*/
public class RocketMQBinderHealthIndicator extends AbstractHealthIndicator {
- @Autowired
- private InstrumentationManager instrumentationManager;
-
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
- if (instrumentationManager.getHealthInstrumentations().stream()
+ if (InstrumentationManager.getHealthInstrumentations().stream()
.allMatch(Instrumentation::isUp)) {
builder.up();
return;
}
- if (instrumentationManager.getHealthInstrumentations().stream()
+ if (InstrumentationManager.getHealthInstrumentations().stream()
.allMatch(Instrumentation::isOutOfService)) {
builder.outOfService();
return;
}
builder.down();
- instrumentationManager.getHealthInstrumentations().stream()
+ InstrumentationManager.getHealthInstrumentations().stream()
.filter(instrumentation -> !instrumentation.isStarted())
.forEach(instrumentation1 -> builder
.withException(instrumentation1.getStartException()));
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java
index fb167c6977..7bd875f33b 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java
@@ -1,465 +1,470 @@
-/*
- * Copyright 2013-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://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 com.alibaba.cloud.stream.binder.rocketmq.consuming;
-
-import java.util.List;
-import java.util.Objects;
-
-import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderUtils;
-import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder;
-import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;
-import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;
-import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper;
-import org.apache.rocketmq.acl.common.AclClientRPCHook;
-import org.apache.rocketmq.acl.common.SessionCredentials;
-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.rebalance.AllocateMessageQueueAveragely;
-import org.apache.rocketmq.client.exception.MQClientException;
-import org.apache.rocketmq.common.UtilAll;
-import org.apache.rocketmq.common.message.MessageExt;
-import org.apache.rocketmq.remoting.RPCHook;
-import org.apache.rocketmq.spring.annotation.ConsumeMode;
-import org.apache.rocketmq.spring.annotation.MessageModel;
-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.support.RocketMQListenerContainer;
-import org.apache.rocketmq.spring.support.RocketMQUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.cloud.stream.binder.ExtendedConsumerProperties;
-import org.springframework.context.SmartLifecycle;
-import org.springframework.integration.support.MessageBuilder;
-import org.springframework.messaging.Message;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
-
-import static com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants.ROCKETMQ_RECONSUME_TIMES;
-
-/**
- * A class that Listen on rocketmq message.
- *
- * this class will delegate {@link RocketMQListener} to handle message
- *
- * @author Jim
- * @author Xiejiashuai
- * @see RocketMQListener
- */
-public class RocketMQListenerBindingContainer
- implements InitializingBean, RocketMQListenerContainer, SmartLifecycle {
-
- private final static Logger log = LoggerFactory
- .getLogger(RocketMQListenerBindingContainer.class);
-
- private long suspendCurrentQueueTimeMillis = 1000;
-
- /**
- * Message consume retry strategy
- * -1,no retry,put into DLQ directly
- * 0,broker control retry frequency
- * >0,client control retry frequency.
- */
- private int delayLevelWhenNextConsume = 0;
-
- private List nameServer;
-
- private String consumerGroup;
-
- private String topic;
-
- private int consumeThreadMax = 64;
-
- private String charset = "UTF-8";
-
- private RocketMQListener rocketMQListener;
-
- private RocketMQHeaderMapper headerMapper;
-
- private DefaultMQPushConsumer consumer;
-
- private boolean running;
-
- private final ExtendedConsumerProperties rocketMQConsumerProperties;
-
- private final RocketMQMessageChannelBinder rocketMQMessageChannelBinder;
-
- private final RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties;
-
- // The following properties came from RocketMQConsumerProperties.
- private ConsumeMode consumeMode;
-
- private SelectorType selectorType;
-
- private String selectorExpression;
-
- private MessageModel messageModel;
-
- public RocketMQListenerBindingContainer(
- ExtendedConsumerProperties rocketMQConsumerProperties,
- RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties,
- RocketMQMessageChannelBinder rocketMQMessageChannelBinder) {
- this.rocketMQConsumerProperties = rocketMQConsumerProperties;
- this.rocketBinderConfigurationProperties = rocketBinderConfigurationProperties;
- this.rocketMQMessageChannelBinder = rocketMQMessageChannelBinder;
- this.consumeMode = rocketMQConsumerProperties.getExtension().getOrderly()
- ? ConsumeMode.ORDERLY : ConsumeMode.CONCURRENTLY;
- if (StringUtils.isEmpty(rocketMQConsumerProperties.getExtension().getSql())) {
- this.selectorType = SelectorType.TAG;
- this.selectorExpression = rocketMQConsumerProperties.getExtension().getTags();
- }
- else {
- this.selectorType = SelectorType.SQL92;
- this.selectorExpression = rocketMQConsumerProperties.getExtension().getSql();
- }
- this.messageModel = rocketMQConsumerProperties.getExtension().getBroadcasting()
- ? MessageModel.BROADCASTING : MessageModel.CLUSTERING;
- }
-
- @Override
- public void setupMessageListener(RocketMQListener> rocketMQListener) {
- this.rocketMQListener = rocketMQListener;
- }
-
- @Override
- public void destroy() throws Exception {
- this.setRunning(false);
- if (Objects.nonNull(consumer)) {
- consumer.shutdown();
- }
- log.info("container destroyed, {}", this.toString());
- }
-
- @Override
- public void afterPropertiesSet() throws Exception {
- initRocketMQPushConsumer();
- }
-
- @Override
- public boolean isAutoStartup() {
- return true;
- }
-
- @Override
- public void stop(Runnable callback) {
- stop();
- callback.run();
- }
-
- @Override
- public void start() {
- if (this.isRunning()) {
- throw new IllegalStateException(
- "container already running. " + this.toString());
- }
-
- try {
- consumer.start();
- }
- catch (MQClientException e) {
- throw new IllegalStateException("Failed to start RocketMQ push consumer", e);
- }
- this.setRunning(true);
-
- log.info("running container: {}", this.toString());
- }
-
- @Override
- public void stop() {
- if (this.isRunning()) {
- if (Objects.nonNull(consumer)) {
- consumer.shutdown();
- }
- setRunning(false);
- }
- }
-
- @Override
- public boolean isRunning() {
- return running;
- }
-
- private void setRunning(boolean running) {
- this.running = running;
- }
-
- @Override
- public int getPhase() {
- return Integer.MAX_VALUE;
- }
-
- private void initRocketMQPushConsumer() throws MQClientException {
- Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required");
- Assert.notNull(consumerGroup, "Property 'consumerGroup' is required");
- Assert.notNull(nameServer, "Property 'nameServer' is required");
- Assert.notNull(topic, "Property 'topic' is required");
-
- String ak = rocketBinderConfigurationProperties.getAccessKey();
- String sk = rocketBinderConfigurationProperties.getSecretKey();
- if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) {
- RPCHook rpcHook = new AclClientRPCHook(new SessionCredentials(ak, sk));
- consumer = new DefaultMQPushConsumer(consumerGroup, rpcHook,
- new AllocateMessageQueueAveragely(),
- rocketBinderConfigurationProperties.isEnableMsgTrace(),
- rocketBinderConfigurationProperties.getCustomizedTraceTopic());
- consumer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook,
- topic + "|" + UtilAll.getPid()));
- consumer.setVipChannelEnabled(false);
- }
- else {
- consumer = new DefaultMQPushConsumer(consumerGroup,
- rocketBinderConfigurationProperties.isEnableMsgTrace(),
- rocketBinderConfigurationProperties.getCustomizedTraceTopic());
- }
-
- consumer.setNamesrvAddr(RocketMQBinderUtils.getNameServerStr(nameServer));
- consumer.setConsumeThreadMax(rocketMQConsumerProperties.getConcurrency());
- consumer.setConsumeThreadMin(rocketMQConsumerProperties.getConcurrency());
-
- switch (messageModel) {
- case BROADCASTING:
- consumer.setMessageModel(
- org.apache.rocketmq.common.protocol.heartbeat.MessageModel.BROADCASTING);
- break;
- case CLUSTERING:
- consumer.setMessageModel(
- org.apache.rocketmq.common.protocol.heartbeat.MessageModel.CLUSTERING);
- break;
- default:
- throw new IllegalArgumentException("Property 'messageModel' was wrong.");
- }
-
- switch (selectorType) {
- case TAG:
- consumer.subscribe(topic, selectorExpression);
- break;
- case SQL92:
- consumer.subscribe(topic, MessageSelector.bySql(selectorExpression));
- break;
- default:
- throw new IllegalArgumentException("Property 'selectorType' was wrong.");
- }
-
- switch (consumeMode) {
- case ORDERLY:
- consumer.setMessageListener(new DefaultMessageListenerOrderly());
- break;
- case CONCURRENTLY:
- consumer.setMessageListener(new DefaultMessageListenerConcurrently());
- break;
- default:
- throw new IllegalArgumentException("Property 'consumeMode' was wrong.");
- }
-
- if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) {
- ((RocketMQPushConsumerLifecycleListener) rocketMQListener)
- .prepareStart(consumer);
- }
-
- }
-
- @Override
- public String toString() {
- return "RocketMQListenerBindingContainer{" + "consumerGroup='" + consumerGroup
- + '\'' + ", nameServer='" + nameServer + '\'' + ", topic='" + topic + '\''
- + ", consumeMode=" + consumeMode + ", selectorType=" + selectorType
- + ", selectorExpression='" + selectorExpression + '\'' + ", messageModel="
- + messageModel + '}';
- }
-
- public long getSuspendCurrentQueueTimeMillis() {
- return suspendCurrentQueueTimeMillis;
- }
-
- public void setSuspendCurrentQueueTimeMillis(long suspendCurrentQueueTimeMillis) {
- this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis;
- }
-
- public int getDelayLevelWhenNextConsume() {
- return delayLevelWhenNextConsume;
- }
-
- public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) {
- this.delayLevelWhenNextConsume = delayLevelWhenNextConsume;
- }
-
- public List getNameServer() {
- return nameServer;
- }
-
- public void setNameServer(List nameServer) {
- this.nameServer = nameServer;
- }
-
- public String getConsumerGroup() {
- return consumerGroup;
- }
-
- public void setConsumerGroup(String consumerGroup) {
- this.consumerGroup = consumerGroup;
- }
-
- public String getTopic() {
- return topic;
- }
-
- public void setTopic(String topic) {
- this.topic = topic;
- }
-
- public int getConsumeThreadMax() {
- return consumeThreadMax;
- }
-
- public void setConsumeThreadMax(int consumeThreadMax) {
- this.consumeThreadMax = consumeThreadMax;
- }
-
- public String getCharset() {
- return charset;
- }
-
- public void setCharset(String charset) {
- this.charset = charset;
- }
-
- public RocketMQListener getRocketMQListener() {
- return rocketMQListener;
- }
-
- public void setRocketMQListener(RocketMQListener rocketMQListener) {
- this.rocketMQListener = rocketMQListener;
- }
-
- public DefaultMQPushConsumer getConsumer() {
- return consumer;
- }
-
- public void setConsumer(DefaultMQPushConsumer consumer) {
- this.consumer = consumer;
- }
-
- public ExtendedConsumerProperties getRocketMQConsumerProperties() {
- return rocketMQConsumerProperties;
- }
-
- public ConsumeMode getConsumeMode() {
- return consumeMode;
- }
-
- public SelectorType getSelectorType() {
- return selectorType;
- }
-
- public String getSelectorExpression() {
- return selectorExpression;
- }
-
- public MessageModel getMessageModel() {
- return messageModel;
- }
-
- public RocketMQHeaderMapper getHeaderMapper() {
- return headerMapper;
- }
-
- public void setHeaderMapper(RocketMQHeaderMapper headerMapper) {
- this.headerMapper = headerMapper;
- }
-
- /**
- * Convert rocketmq {@link MessageExt} to Spring {@link Message}.
- * @param messageExt the rocketmq message
- * @return the converted Spring {@link Message}
- */
- @SuppressWarnings("unchecked")
- private Message convertToSpringMessage(MessageExt messageExt) {
-
- // add reconsume-times header to messageExt
- int reconsumeTimes = messageExt.getReconsumeTimes();
- messageExt.putUserProperty(ROCKETMQ_RECONSUME_TIMES,
- String.valueOf(reconsumeTimes));
- Message message = RocketMQUtil.convertToSpringMessage(messageExt);
- return MessageBuilder.fromMessage(message)
- .copyHeaders(headerMapper.toHeaders(messageExt.getProperties())).build();
- }
-
- public class DefaultMessageListenerConcurrently
- implements MessageListenerConcurrently {
-
- @SuppressWarnings({ "unchecked", "Duplicates" })
- @Override
- public ConsumeConcurrentlyStatus consumeMessage(List msgs,
- ConsumeConcurrentlyContext context) {
- for (MessageExt messageExt : msgs) {
- log.debug("received msg: {}", messageExt);
- try {
- long now = System.currentTimeMillis();
- rocketMQListener.onMessage(convertToSpringMessage(messageExt));
- long costTime = System.currentTimeMillis() - now;
- log.debug("consume {} message key:[{}] cost: {} ms",
- messageExt.getMsgId(), messageExt.getKeys(), 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", "Duplicates" })
- @Override
- public ConsumeOrderlyStatus consumeMessage(List msgs,
- ConsumeOrderlyContext context) {
- for (MessageExt messageExt : msgs) {
- log.debug("received msg: {}", messageExt);
- try {
- long now = System.currentTimeMillis();
- rocketMQListener.onMessage(convertToSpringMessage(messageExt));
- long costTime = System.currentTimeMillis() - now;
- log.info("consume {} message key:[{}] cost: {} ms",
- messageExt.getMsgId(), messageExt.getKeys(), 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;
- }
-
- }
-
-}
+/// *
+// * Copyright 2013-2018 the original author or authors.
+// *
+// * Licensed under the Apache License, Version 2.0 (the "License");
+// * you may not use this file except in compliance with the License.
+// * You may obtain a copy of the License at
+// *
+// * https://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 com.alibaba.cloud.stream.binder.rocketmq.consuming;
+//
+// import java.util.List;
+// import java.util.Objects;
+//
+// import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderUtils;
+// import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder;
+// import
+/// com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;
+// import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;
+// import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper;
+// import org.apache.rocketmq.acl.common.AclClientRPCHook;
+// import org.apache.rocketmq.acl.common.SessionCredentials;
+// 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.rebalance.AllocateMessageQueueAveragely;
+// import org.apache.rocketmq.client.exception.MQClientException;
+// import org.apache.rocketmq.common.UtilAll;
+// import org.apache.rocketmq.common.message.MessageExt;
+// import org.apache.rocketmq.remoting.RPCHook;
+// import org.apache.rocketmq.spring.annotation.ConsumeMode;
+// import org.apache.rocketmq.spring.annotation.MessageModel;
+// 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.support.RocketMQListenerContainer;
+// import org.apache.rocketmq.spring.support.RocketMQUtil;
+// import org.slf4j.Logger;
+// import org.slf4j.LoggerFactory;
+//
+// import org.springframework.beans.factory.InitializingBean;
+// import org.springframework.cloud.stream.binder.ExtendedConsumerProperties;
+// import org.springframework.context.SmartLifecycle;
+// import org.springframework.integration.support.MessageBuilder;
+// import org.springframework.messaging.Message;
+// import org.springframework.util.Assert;
+// import org.springframework.util.StringUtils;
+//
+// import static
+/// com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants.ROCKETMQ_RECONSUME_TIMES;
+//
+/// **
+// * A class that Listen on rocketmq message.
+// *
+// * this class will delegate {@link RocketMQListener} to handle message
+// *
+// * @author Jim
+// * @author Xiejiashuai
+// * @see RocketMQListener
+// */
+// public class RocketMQListenerBindingContainer
+// implements InitializingBean, RocketMQListenerContainer, SmartLifecycle {
+//
+// private final static Logger log = LoggerFactory
+// .getLogger(RocketMQListenerBindingContainer.class);
+//
+// private long suspendCurrentQueueTimeMillis = 1000;
+//
+// /**
+// * Message consume retry strategy
+// * -1,no retry,put into DLQ directly
+// * 0,broker control retry frequency
+// * >0,client control retry frequency.
+// */
+// private int delayLevelWhenNextConsume = 0;
+//
+// private List nameServer;
+//
+// private String consumerGroup;
+//
+// private String topic;
+//
+// private int consumeThreadMax = 64;
+//
+// private String charset = "UTF-8";
+//
+// private RocketMQListener rocketMQListener;
+//
+// private RocketMQHeaderMapper headerMapper;
+//
+// private DefaultMQPushConsumer consumer;
+//
+// private boolean running;
+//
+// private final ExtendedConsumerProperties
+/// rocketMQConsumerProperties;
+//
+// private final RocketMQMessageChannelBinder rocketMQMessageChannelBinder;
+//
+// private final RocketMQBinderConfigurationProperties
+/// rocketBinderConfigurationProperties;
+//
+// // The following properties came from RocketMQConsumerProperties.
+// private ConsumeMode consumeMode;
+//
+// private SelectorType selectorType;
+//
+// private String selectorExpression;
+//
+// private MessageModel messageModel;
+//
+// public RocketMQListenerBindingContainer(
+// ExtendedConsumerProperties rocketMQConsumerProperties,
+// RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties,
+// RocketMQMessageChannelBinder rocketMQMessageChannelBinder) {
+// this.rocketMQConsumerProperties = rocketMQConsumerProperties;
+// this.rocketBinderConfigurationProperties = rocketBinderConfigurationProperties;
+// this.rocketMQMessageChannelBinder = rocketMQMessageChannelBinder;
+// this.consumeMode = rocketMQConsumerProperties.getExtension().getOrderly()
+// ? ConsumeMode.ORDERLY : ConsumeMode.CONCURRENTLY;
+// if (StringUtils.isEmpty(rocketMQConsumerProperties.getExtension().getSql())) {
+// this.selectorType = SelectorType.TAG;
+// this.selectorExpression = rocketMQConsumerProperties.getExtension().getTags();
+// }
+// else {
+// this.selectorType = SelectorType.SQL92;
+// this.selectorExpression = rocketMQConsumerProperties.getExtension().getSql();
+// }
+// this.messageModel = rocketMQConsumerProperties.getExtension().getBroadcasting()
+// ? MessageModel.BROADCASTING : MessageModel.CLUSTERING;
+// }
+//
+// @Override
+// public void setupMessageListener(RocketMQListener> rocketMQListener) {
+// this.rocketMQListener = rocketMQListener;
+// }
+//
+// @Override
+// public void destroy() throws Exception {
+// this.setRunning(false);
+// if (Objects.nonNull(consumer)) {
+// consumer.shutdown();
+// }
+// log.info("container destroyed, {}", this.toString());
+// }
+//
+// @Override
+// public void afterPropertiesSet() throws Exception {
+// initRocketMQPushConsumer();
+// }
+//
+// @Override
+// public boolean isAutoStartup() {
+// return true;
+// }
+//
+// @Override
+// public void stop(Runnable callback) {
+// stop();
+// callback.run();
+// }
+//
+// @Override
+// public void start() {
+// if (this.isRunning()) {
+// throw new IllegalStateException(
+// "container already running. " + this.toString());
+// }
+//
+// try {
+// consumer.start();
+// }
+// catch (MQClientException e) {
+// throw new IllegalStateException("Failed to start RocketMQ push consumer", e);
+// }
+// this.setRunning(true);
+//
+// log.info("running container: {}", this.toString());
+// }
+//
+// @Override
+// public void stop() {
+// if (this.isRunning()) {
+// if (Objects.nonNull(consumer)) {
+// consumer.shutdown();
+// }
+// setRunning(false);
+// }
+// }
+//
+// @Override
+// public boolean isRunning() {
+// return running;
+// }
+//
+// private void setRunning(boolean running) {
+// this.running = running;
+// }
+//
+// @Override
+// public int getPhase() {
+// return Integer.MAX_VALUE;
+// }
+//
+// private void initRocketMQPushConsumer() throws MQClientException {
+// Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required");
+// Assert.notNull(consumerGroup, "Property 'consumerGroup' is required");
+// Assert.notNull(nameServer, "Property 'nameServer' is required");
+// Assert.notNull(topic, "Property 'topic' is required");
+//
+// String ak = rocketBinderConfigurationProperties.getAccessKey();
+// String sk = rocketBinderConfigurationProperties.getSecretKey();
+// if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) {
+// RPCHook rpcHook = new AclClientRPCHook(new SessionCredentials(ak, sk));
+// consumer = new DefaultMQPushConsumer(consumerGroup, rpcHook,
+// new AllocateMessageQueueAveragely(),
+// rocketBinderConfigurationProperties.isEnableMsgTrace(),
+// rocketBinderConfigurationProperties.getCustomizedTraceTopic());
+// consumer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook,
+// topic + "|" + UtilAll.getPid()));
+// consumer.setVipChannelEnabled(false);
+// }
+// else {
+// consumer = new DefaultMQPushConsumer(consumerGroup,
+// rocketBinderConfigurationProperties.isEnableMsgTrace(),
+// rocketBinderConfigurationProperties.getCustomizedTraceTopic());
+// }
+//
+// consumer.setNamesrvAddr(RocketMQBinderUtils.getNameServerStr(nameServer));
+// consumer.setConsumeThreadMax(rocketMQConsumerProperties.getConcurrency());
+// consumer.setConsumeThreadMin(rocketMQConsumerProperties.getConcurrency());
+//
+// switch (messageModel) {
+// case BROADCASTING:
+// consumer.setMessageModel(
+// org.apache.rocketmq.common.protocol.heartbeat.MessageModel.BROADCASTING);
+// break;
+// case CLUSTERING:
+// consumer.setMessageModel(
+// org.apache.rocketmq.common.protocol.heartbeat.MessageModel.CLUSTERING);
+// break;
+// default:
+// throw new IllegalArgumentException("Property 'messageModel' was wrong.");
+// }
+//
+// switch (selectorType) {
+// case TAG:
+// consumer.subscribe(topic, selectorExpression);
+// break;
+// case SQL92:
+// consumer.subscribe(topic, MessageSelector.bySql(selectorExpression));
+// break;
+// default:
+// throw new IllegalArgumentException("Property 'selectorType' was wrong.");
+// }
+//
+// switch (consumeMode) {
+// case ORDERLY:
+// consumer.setMessageListener(new DefaultMessageListenerOrderly());
+// break;
+// case CONCURRENTLY:
+// consumer.setMessageListener(new DefaultMessageListenerConcurrently());
+// break;
+// default:
+// throw new IllegalArgumentException("Property 'consumeMode' was wrong.");
+// }
+//
+// if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) {
+// ((RocketMQPushConsumerLifecycleListener) rocketMQListener)
+// .prepareStart(consumer);
+// }
+//
+// }
+//
+// @Override
+// public String toString() {
+// return "RocketMQListenerBindingContainer{" + "consumerGroup='" + consumerGroup
+// + '\'' + ", nameServer='" + nameServer + '\'' + ", topic='" + topic + '\''
+// + ", consumeMode=" + consumeMode + ", selectorType=" + selectorType
+// + ", selectorExpression='" + selectorExpression + '\'' + ", messageModel="
+// + messageModel + '}';
+// }
+//
+// public long getSuspendCurrentQueueTimeMillis() {
+// return suspendCurrentQueueTimeMillis;
+// }
+//
+// public void setSuspendCurrentQueueTimeMillis(long suspendCurrentQueueTimeMillis) {
+// this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis;
+// }
+//
+// public int getDelayLevelWhenNextConsume() {
+// return delayLevelWhenNextConsume;
+// }
+//
+// public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) {
+// this.delayLevelWhenNextConsume = delayLevelWhenNextConsume;
+// }
+//
+// public List getNameServer() {
+// return nameServer;
+// }
+//
+// public void setNameServer(List nameServer) {
+// this.nameServer = nameServer;
+// }
+//
+// public String getConsumerGroup() {
+// return consumerGroup;
+// }
+//
+// public void setConsumerGroup(String consumerGroup) {
+// this.consumerGroup = consumerGroup;
+// }
+//
+// public String getTopic() {
+// return topic;
+// }
+//
+// public void setTopic(String topic) {
+// this.topic = topic;
+// }
+//
+// public int getConsumeThreadMax() {
+// return consumeThreadMax;
+// }
+//
+// public void setConsumeThreadMax(int consumeThreadMax) {
+// this.consumeThreadMax = consumeThreadMax;
+// }
+//
+// public String getCharset() {
+// return charset;
+// }
+//
+// public void setCharset(String charset) {
+// this.charset = charset;
+// }
+//
+// public RocketMQListener getRocketMQListener() {
+// return rocketMQListener;
+// }
+//
+// public void setRocketMQListener(RocketMQListener rocketMQListener) {
+// this.rocketMQListener = rocketMQListener;
+// }
+//
+// public DefaultMQPushConsumer getConsumer() {
+// return consumer;
+// }
+//
+// public void setConsumer(DefaultMQPushConsumer consumer) {
+// this.consumer = consumer;
+// }
+//
+// public ExtendedConsumerProperties
+/// getRocketMQConsumerProperties() {
+// return rocketMQConsumerProperties;
+// }
+//
+// public ConsumeMode getConsumeMode() {
+// return consumeMode;
+// }
+//
+// public SelectorType getSelectorType() {
+// return selectorType;
+// }
+//
+// public String getSelectorExpression() {
+// return selectorExpression;
+// }
+//
+// public MessageModel getMessageModel() {
+// return messageModel;
+// }
+//
+// public RocketMQHeaderMapper getHeaderMapper() {
+// return headerMapper;
+// }
+//
+// public void setHeaderMapper(RocketMQHeaderMapper headerMapper) {
+// this.headerMapper = headerMapper;
+// }
+//
+// /**
+// * Convert rocketmq {@link MessageExt} to Spring {@link Message}.
+// * @param messageExt the rocketmq message
+// * @return the converted Spring {@link Message}
+// */
+// @SuppressWarnings("unchecked")
+// private Message convertToSpringMessage(MessageExt messageExt) {
+//
+// // add reconsume-times header to messageExt
+// int reconsumeTimes = messageExt.getReconsumeTimes();
+// messageExt.putUserProperty(ROCKETMQ_RECONSUME_TIMES,
+// String.valueOf(reconsumeTimes));
+// Message message = RocketMQUtil.convertToSpringMessage(messageExt);
+// return MessageBuilder.fromMessage(message)
+// .copyHeaders(headerMapper.toHeaders(messageExt.getProperties())).build();
+// }
+//
+// public class DefaultMessageListenerConcurrently
+// implements MessageListenerConcurrently {
+//
+// @SuppressWarnings({ "unchecked", "Duplicates" })
+// @Override
+// public ConsumeConcurrentlyStatus consumeMessage(List msgs,
+// ConsumeConcurrentlyContext context) {
+// for (MessageExt messageExt : msgs) {
+// log.debug("received msg: {}", messageExt);
+// try {
+// long now = System.currentTimeMillis();
+// rocketMQListener.onMessage(convertToSpringMessage(messageExt));
+// long costTime = System.currentTimeMillis() - now;
+// log.debug("consume {} message key:[{}] cost: {} ms",
+// messageExt.getMsgId(), messageExt.getKeys(), 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", "Duplicates" })
+// @Override
+// public ConsumeOrderlyStatus consumeMessage(List msgs,
+// ConsumeOrderlyContext context) {
+// for (MessageExt messageExt : msgs) {
+// log.debug("received msg: {}", messageExt);
+// try {
+// long now = System.currentTimeMillis();
+// rocketMQListener.onMessage(convertToSpringMessage(messageExt));
+// long costTime = System.currentTimeMillis() - now;
+// log.info("consume {} message key:[{}] cost: {} ms",
+// messageExt.getMsgId(), messageExt.getKeys(), 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/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQInboundChannelAdapter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQInboundChannelAdapter.java
deleted file mode 100644
index a3b6804193..0000000000
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/RocketMQInboundChannelAdapter.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 2013-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://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 com.alibaba.cloud.stream.binder.rocketmq.integration;
-
-import com.alibaba.cloud.stream.binder.rocketmq.consuming.RocketMQListenerBindingContainer;
-import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation;
-import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager;
-import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;
-import org.apache.rocketmq.spring.core.RocketMQListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.springframework.cloud.stream.binder.ExtendedConsumerProperties;
-import org.springframework.integration.endpoint.MessageProducerSupport;
-import org.springframework.integration.support.MessageBuilder;
-import org.springframework.messaging.Message;
-import org.springframework.messaging.MessagingException;
-import org.springframework.retry.RecoveryCallback;
-import org.springframework.retry.RetryCallback;
-import org.springframework.retry.RetryContext;
-import org.springframework.retry.RetryListener;
-import org.springframework.retry.support.RetryTemplate;
-import org.springframework.util.Assert;
-
-/**
- * @author Jim
- */
-public class RocketMQInboundChannelAdapter extends MessageProducerSupport {
-
- private static final Logger log = LoggerFactory
- .getLogger(RocketMQInboundChannelAdapter.class);
-
- private RetryTemplate retryTemplate;
-
- private RecoveryCallback extends Object> recoveryCallback;
-
- private RocketMQListenerBindingContainer rocketMQListenerContainer;
-
- private final ExtendedConsumerProperties consumerProperties;
-
- private final InstrumentationManager instrumentationManager;
-
- public RocketMQInboundChannelAdapter(
- RocketMQListenerBindingContainer rocketMQListenerContainer,
- ExtendedConsumerProperties consumerProperties,
- InstrumentationManager instrumentationManager) {
- this.rocketMQListenerContainer = rocketMQListenerContainer;
- this.consumerProperties = consumerProperties;
- this.instrumentationManager = instrumentationManager;
- }
-
- @Override
- protected void onInit() {
- if (consumerProperties == null
- || !consumerProperties.getExtension().getEnabled()) {
- return;
- }
- super.onInit();
- if (this.retryTemplate != null) {
- Assert.state(getErrorChannel() == null,
- "Cannot have an 'errorChannel' property when a 'RetryTemplate' is "
- + "provided; use an 'ErrorMessageSendingRecoverer' in the 'recoveryCallback' property to "
- + "send an error message when retries are exhausted");
- }
-
- BindingRocketMQListener listener = new BindingRocketMQListener();
- rocketMQListenerContainer.setRocketMQListener(listener);
-
- if (retryTemplate != null) {
- this.retryTemplate.registerListener(listener);
- }
-
- try {
- rocketMQListenerContainer.afterPropertiesSet();
-
- }
- catch (Exception e) {
- log.error("rocketMQListenerContainer init error: " + e.getMessage(), e);
- throw new IllegalArgumentException(
- "rocketMQListenerContainer init error: " + e.getMessage(), e);
- }
-
- instrumentationManager.addHealthInstrumentation(
- new Instrumentation(rocketMQListenerContainer.getTopic()
- + rocketMQListenerContainer.getConsumerGroup()));
- }
-
- @Override
- protected void doStart() {
- if (consumerProperties == null
- || !consumerProperties.getExtension().getEnabled()) {
- return;
- }
- try {
- rocketMQListenerContainer.start();
- instrumentationManager
- .getHealthInstrumentation(rocketMQListenerContainer.getTopic()
- + rocketMQListenerContainer.getConsumerGroup())
- .markStartedSuccessfully();
- }
- catch (Exception e) {
- instrumentationManager
- .getHealthInstrumentation(rocketMQListenerContainer.getTopic()
- + rocketMQListenerContainer.getConsumerGroup())
- .markStartFailed(e);
- log.error("RocketMQTemplate startup failed, Caused by " + e.getMessage());
- throw new MessagingException(MessageBuilder.withPayload(
- "RocketMQTemplate startup failed, Caused by " + e.getMessage())
- .build(), e);
- }
- }
-
- @Override
- protected void doStop() {
- rocketMQListenerContainer.stop();
- }
-
- public void setRetryTemplate(RetryTemplate retryTemplate) {
- this.retryTemplate = retryTemplate;
- }
-
- public void setRecoveryCallback(RecoveryCallback extends Object> recoveryCallback) {
- this.recoveryCallback = recoveryCallback;
- }
-
- protected class BindingRocketMQListener
- implements RocketMQListener, RetryListener {
-
- @Override
- public void onMessage(Message message) {
- boolean enableRetry = RocketMQInboundChannelAdapter.this.retryTemplate != null;
- if (enableRetry) {
- RocketMQInboundChannelAdapter.this.retryTemplate.execute(context -> {
- RocketMQInboundChannelAdapter.this.sendMessage(message);
- return null;
- }, (RecoveryCallback
+ *
+ * This field defaults to clustering.
*/
- private String tags;
+ private String messageModel = MessageModel.CLUSTERING.getModeCN();
/**
- * {@link MQPushConsumer#subscribe(String, MessageSelector)}
- * {@link MessageSelector#bySql(String)}.
+ * Queue allocation algorithm specifying how message queues are allocated to each
+ * consumer clients.
*/
- private String sql;
+ private String allocateMessageQueueStrategy;
/**
- * {@link MessageModel#BROADCASTING}.
+ * The expressions include tags or SQL,as follow:
+ *
+ * tag: {@code tag1||tag2||tag3 }; sql: {@code 'color'='blue' AND 'price'>100 } .
+ *
+ * Determines whether there are specific characters "{@code ||}" in the expression to
+ * determine how the message is filtered,tags or SQL.
*/
- private Boolean broadcasting = false;
+ private String subscription;
/**
- * if orderly is true, using {@link MessageListenerOrderly} else if orderly if false,
- * using {@link MessageListenerConcurrently}.
+ * Delay some time when exception occur
*/
- private Boolean orderly = false;
+ private long pullTimeDelayMillsWhenException = 1000;
/**
- * for concurrently listener. message consume retry strategy. see
- * {@link ConsumeConcurrentlyContext#delayLevelWhenNextConsume}. -1 means dlq(or
- * discard, see {@link this#shouldRequeue}), others means requeue.
+ * Consuming point on consumer booting.
+ *
+ *
+ * There are three consuming points:
+ *
+ *
CONSUME_FROM_LAST_OFFSET: consumer clients pick up where it
+ * stopped previously. If it were a newly booting up consumer client, according aging
+ * of the consumer group, there are two cases:
+ *
+ *
if the consumer group is created so recently that the earliest message being
+ * subscribed has yet expired, which means the consumer group represents a lately
+ * launched business, consuming will start from the very beginning;
+ *
if the earliest message being subscribed has expired, consuming will start from
+ * the latest messages, meaning messages born prior to the booting timestamp would be
+ * ignored.
+ *
+ *
+ *
CONSUME_FROM_FIRST_OFFSET: Consumer client will start from
+ * earliest messages available.
+ *
CONSUME_FROM_TIMESTAMP: Consumer client will start from specified
+ * timestamp, which means messages born prior to {@link #consumeTimestamp} will be
+ * ignored
+ *
+ */
+ private ConsumeFromWhere consumeFromWhere = ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET;
+ /**
+ * Backtracking consumption time with second precision. Time format is
+ * 20131223171201
+ * Implying Seventeen twelve and 01 seconds on December 23, 2013 year
+ * Default backtracking consumption time Half an hour ago.
*/
- private int delayLevelWhenNextConsume = 0;
+ private String consumeTimestamp = UtilAll
+ .timeMillisToHumanString3(System.currentTimeMillis() - (1000 * 60 * 30));
/**
- * for orderly listener. next retry delay time.
+ * Flow control threshold on queue level, each message queue will cache at most 1000
+ * messages by default, Consider the {@link #pullBatchSize}, the instantaneous value
+ * may exceed the limit
*/
- private long suspendCurrentQueueTimeMillis = 1000;
+ private int pullThresholdForQueue = 1000;
+ /**
+ * Limit the cached message size on queue level, each message queue will cache at most
+ * 100 MiB messages by default, Consider the {@link #pullBatchSize}, the instantaneous
+ * value may exceed the limit
+ *
+ *
+ * The size of a message only measured by message body, so it's not accurate
+ */
+ private int pullThresholdSizeForQueue = 100;
- private Boolean enabled = true;
+ /**
+ * Maximum number of messages pulled each time.
+ */
+ private int pullBatchSize = 10;
/**
- * {@link JacksonRocketMQHeaderMapper#addTrustedPackages(String...)}.
+ * Consume max span offset.it has no effect on sequential consumption.
*/
- private Set trustedPackages;
+ private int consumeMaxSpan = 2000;
- // ------------ For Pull Consumer ------------
+ private Push push = new Push();
+ private Pull pull = new Pull();
- private long pullTimeout = 10 * 1000;
+ public String getMessageModel() {
+ return messageModel;
+ }
+
+ public RocketMQConsumerProperties setMessageModel(String messageModel) {
+ this.messageModel = messageModel;
+ return this;
+ }
- private boolean fromStore;
+ public String getAllocateMessageQueueStrategy() {
+ return allocateMessageQueueStrategy;
+ }
- // ------------ For Pull Consumer ------------
+ public void setAllocateMessageQueueStrategy(String allocateMessageQueueStrategy) {
+ this.allocateMessageQueueStrategy = allocateMessageQueueStrategy;
+ }
+
+ public String getSubscription() {
+ return subscription;
+ }
- public String getTags() {
- return tags;
+ public void setSubscription(String subscription) {
+ this.subscription = subscription;
}
- public void setTags(String tags) {
- this.tags = tags;
+ public Push getPush() {
+ return push;
}
- public String getSql() {
- return sql;
+ public void setPush(Push push) {
+ this.push = push;
}
- public void setSql(String sql) {
- this.sql = sql;
+ public long getPullTimeDelayMillsWhenException() {
+ return pullTimeDelayMillsWhenException;
}
- public Boolean getOrderly() {
- return orderly;
+ public RocketMQConsumerProperties setPullTimeDelayMillsWhenException(
+ long pullTimeDelayMillsWhenException) {
+ this.pullTimeDelayMillsWhenException = pullTimeDelayMillsWhenException;
+ return this;
}
- public void setOrderly(Boolean orderly) {
- this.orderly = orderly;
+ public ConsumeFromWhere getConsumeFromWhere() {
+ return consumeFromWhere;
}
- public Boolean getEnabled() {
- return enabled;
+ public RocketMQConsumerProperties setConsumeFromWhere(
+ ConsumeFromWhere consumeFromWhere) {
+ this.consumeFromWhere = consumeFromWhere;
+ return this;
}
- public void setEnabled(Boolean enabled) {
- this.enabled = enabled;
+ public String getConsumeTimestamp() {
+ return consumeTimestamp;
}
- public Boolean getBroadcasting() {
- return broadcasting;
+ public RocketMQConsumerProperties setConsumeTimestamp(String consumeTimestamp) {
+ this.consumeTimestamp = consumeTimestamp;
+ return this;
}
- public void setBroadcasting(Boolean broadcasting) {
- this.broadcasting = broadcasting;
+ public int getPullThresholdForQueue() {
+ return pullThresholdForQueue;
}
- public int getDelayLevelWhenNextConsume() {
- return delayLevelWhenNextConsume;
+ public RocketMQConsumerProperties setPullThresholdForQueue(
+ int pullThresholdForQueue) {
+ this.pullThresholdForQueue = pullThresholdForQueue;
+ return this;
}
- public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) {
- this.delayLevelWhenNextConsume = delayLevelWhenNextConsume;
+ public int getPullThresholdSizeForQueue() {
+ return pullThresholdSizeForQueue;
}
- public long getSuspendCurrentQueueTimeMillis() {
- return suspendCurrentQueueTimeMillis;
+ public RocketMQConsumerProperties setPullThresholdSizeForQueue(
+ int pullThresholdSizeForQueue) {
+ this.pullThresholdSizeForQueue = pullThresholdSizeForQueue;
+ return this;
}
- public void setSuspendCurrentQueueTimeMillis(long suspendCurrentQueueTimeMillis) {
- this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis;
+ public int getPullBatchSize() {
+ return pullBatchSize;
}
- public long getPullTimeout() {
- return pullTimeout;
+ public RocketMQConsumerProperties setPullBatchSize(int pullBatchSize) {
+ this.pullBatchSize = pullBatchSize;
+ return this;
}
- public void setPullTimeout(long pullTimeout) {
- this.pullTimeout = pullTimeout;
+ public Pull getPull() {
+ return pull;
}
- public boolean isFromStore() {
- return fromStore;
+ public RocketMQConsumerProperties setPull(Pull pull) {
+ this.pull = pull;
+ return this;
}
- public void setFromStore(boolean fromStore) {
- this.fromStore = fromStore;
+ public int getConsumeMaxSpan() {
+ return consumeMaxSpan;
}
- public boolean shouldRequeue() {
- return delayLevelWhenNextConsume != -1;
+ public RocketMQConsumerProperties setConsumeMaxSpan(int consumeMaxSpan) {
+ this.consumeMaxSpan = consumeMaxSpan;
+ return this;
}
- public Set getTrustedPackages() {
- return trustedPackages;
+ public static class Push implements Serializable {
+ private static final long serialVersionUID = -7398468554978817630L;
+
+ /**
+ * if orderly is true, using {@link MessageListenerOrderly} else if orderly if
+ * false, using {@link MessageListenerConcurrently}.
+ */
+ private boolean orderly = false;
+ /**
+ * Suspending pulling time for cases requiring slow pulling like flow-control
+ * scenario. see{@link ConsumeMessageOrderlyService#processConsumeResult}.
+ * see{@link ConsumeOrderlyContext#getSuspendCurrentQueueTimeMillis}.
+ */
+ private int suspendCurrentQueueTimeMillis = 1000;
+
+ /**
+ * https://github.com/alibaba/spring-cloud-alibaba/issues/1866 Max re-consume
+ * times. -1 means 16 times.
+ *
+ * If messages are re-consumed more than {@link #maxReconsumeTimes} before
+ * success, it's be directed to a deletion queue waiting.
+ */
+ private int maxReconsumeTimes;
+
+ /**
+ * for concurrently listener. message consume retry strategy. -1 means dlq(or
+ * discard. see {@link ConsumeMessageConcurrentlyService#processConsumeResult}.
+ * see {@link ConsumeConcurrentlyContext#getDelayLevelWhenNextConsume}.
+ */
+ private int delayLevelWhenNextConsume = 0;
+
+ /**
+ * Flow control threshold on topic level, default value is -1(Unlimited)
+ *
+ * The value of {@code pullThresholdForQueue} will be overwrote and calculated
+ * based on {@code pullThresholdForTopic} if it is't unlimited
+ *
+ * For example, if the value of pullThresholdForTopic is 1000 and 10 message
+ * queues are assigned to this consumer, then pullThresholdForQueue will be set to
+ * 100.
+ */
+ private int pullThresholdForTopic = -1;
+
+ /**
+ * Limit the cached message size on topic level, default value is -1
+ * MiB(Unlimited)
+ *
+ * The value of {@code pullThresholdSizeForQueue} will be overwrote and calculated
+ * based on {@code pullThresholdSizeForTopic} if it is't unlimited
+ *
+ * For example, if the value of pullThresholdSizeForTopic is 1000 MiB and 10
+ * message queues are assigned to this consumer, then pullThresholdSizeForQueue
+ * will be set to 100 MiB
+ */
+ private int pullThresholdSizeForTopic = -1;
+
+ /**
+ * Message pull Interval
+ */
+ private long pullInterval = 0;
+
+ /**
+ * Batch consumption size
+ */
+ private int consumeMessageBatchMaxSize = 1;
+
+ public boolean getOrderly() {
+ return orderly;
+ }
+
+ public void setOrderly(boolean orderly) {
+ this.orderly = orderly;
+ }
+
+ public int getSuspendCurrentQueueTimeMillis() {
+ return suspendCurrentQueueTimeMillis;
+ }
+
+ public void setSuspendCurrentQueueTimeMillis(int suspendCurrentQueueTimeMillis) {
+ this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis;
+ }
+
+ public int getMaxReconsumeTimes() {
+ return maxReconsumeTimes;
+ }
+
+ public void setMaxReconsumeTimes(int maxReconsumeTimes) {
+ this.maxReconsumeTimes = maxReconsumeTimes;
+ }
+
+ public int getDelayLevelWhenNextConsume() {
+ return delayLevelWhenNextConsume;
+ }
+
+ public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) {
+ this.delayLevelWhenNextConsume = delayLevelWhenNextConsume;
+ }
+
+ public int getPullThresholdForTopic() {
+ return pullThresholdForTopic;
+ }
+
+ public void setPullThresholdForTopic(int pullThresholdForTopic) {
+ this.pullThresholdForTopic = pullThresholdForTopic;
+ }
+
+ public int getPullThresholdSizeForTopic() {
+ return pullThresholdSizeForTopic;
+ }
+
+ public void setPullThresholdSizeForTopic(int pullThresholdSizeForTopic) {
+ this.pullThresholdSizeForTopic = pullThresholdSizeForTopic;
+ }
+
+ public long getPullInterval() {
+ return pullInterval;
+ }
+
+ public void setPullInterval(long pullInterval) {
+ this.pullInterval = pullInterval;
+ }
+
+ public int getConsumeMessageBatchMaxSize() {
+ return consumeMessageBatchMaxSize;
+ }
+
+ public void setConsumeMessageBatchMaxSize(int consumeMessageBatchMaxSize) {
+ this.consumeMessageBatchMaxSize = consumeMessageBatchMaxSize;
+ }
}
- public void setTrustedPackages(Set trustedPackages) {
- this.trustedPackages = trustedPackages;
+ public static class Pull implements Serializable {
+ /**
+ * The poll timeout in milliseconds
+ */
+ private long pollTimeoutMillis = 1000 * 5;
+ /**
+ * Pull thread number
+ */
+ private int pullThreadNums = 20;
+
+ /**
+ * Interval time in in milliseconds for checking changes in topic metadata.
+ */
+ private long topicMetadataCheckIntervalMillis = 30 * 1000;
+
+ /**
+ * Long polling mode, the Consumer connection timeout(must greater than
+ * brokerSuspendMaxTimeMillis), it is not recommended to modify
+ */
+ private long consumerTimeoutMillisWhenSuspend = 1000 * 30;
+
+ /**
+ * Ack state handling, including receive, reject, and retry, when a consumption
+ * exception occurs. see {@link }
+ */
+ private String errAcknowledge;
+
+ private long pullThresholdForAll = 1000L;
+
+ public long getPollTimeoutMillis() {
+ return pollTimeoutMillis;
+ }
+
+ public void setPollTimeoutMillis(long pollTimeoutMillis) {
+ this.pollTimeoutMillis = pollTimeoutMillis;
+ }
+
+ public int getPullThreadNums() {
+ return pullThreadNums;
+ }
+
+ public void setPullThreadNums(int pullThreadNums) {
+ this.pullThreadNums = pullThreadNums;
+ }
+
+ public long getTopicMetadataCheckIntervalMillis() {
+ return topicMetadataCheckIntervalMillis;
+ }
+
+ public void setTopicMetadataCheckIntervalMillis(
+ long topicMetadataCheckIntervalMillis) {
+ this.topicMetadataCheckIntervalMillis = topicMetadataCheckIntervalMillis;
+ }
+
+ public long getConsumerTimeoutMillisWhenSuspend() {
+ return consumerTimeoutMillisWhenSuspend;
+ }
+
+ public void setConsumerTimeoutMillisWhenSuspend(
+ long consumerTimeoutMillisWhenSuspend) {
+ this.consumerTimeoutMillisWhenSuspend = consumerTimeoutMillisWhenSuspend;
+ }
+
+ public String getErrAcknowledge() {
+ return errAcknowledge;
+ }
+
+ public void setErrAcknowledge(String errAcknowledge) {
+ this.errAcknowledge = errAcknowledge;
+ }
+
+ public long getPullThresholdForAll() {
+ return pullThresholdForAll;
+ }
+
+ public void setPullThresholdForAll(long pullThresholdForAll) {
+ this.pullThresholdForAll = pullThresholdForAll;
+ }
}
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java
index 890d225001..5fc34ed087 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2013-2018 the original author or authors.
+ * Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * https://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -21,12 +21,14 @@
import org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider;
/**
- * @author Timur Valiev
+ * rocketMQ specific extended binding properties class that extends from
+ * {@link AbstractExtendedBindingProperties}.
+ *
* @author Jim
*/
@ConfigurationProperties("spring.cloud.stream.rocketmq")
public class RocketMQExtendedBindingProperties extends
- AbstractExtendedBindingProperties {
+ AbstractExtendedBindingProperties {
private static final String DEFAULTS_PREFIX = "spring.cloud.stream.rocketmq.default";
@@ -37,7 +39,7 @@ public String getDefaultsPrefix() {
@Override
public Class extends BinderSpecificPropertiesProvider> getExtendedPropertiesEntryClass() {
- return RocketMQBindingProperties.class;
+ return RocketMQSpecificPropertiesProvider.class;
}
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java
index ab2a92a3a9..8f73cf93f4 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java
@@ -1,11 +1,11 @@
/*
- * Copyright 2013-2018 the original author or authors.
+ * Copyright (C) 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * https://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -16,55 +16,39 @@
package com.alibaba.cloud.stream.binder.rocketmq.properties;
-import org.apache.rocketmq.client.producer.DefaultMQProducer;
-
/**
- * @author Timur Valiev
+ * Extended producer properties for RocketMQ binder.
+ *
* @author Jim
*/
-public class RocketMQProducerProperties {
-
- private Boolean enabled = true;
+public class RocketMQProducerProperties extends RocketMQCommonProperties {
/**
- * Name of producer.
+ * Timeout for sending messages.
*/
- private String group;
-
- /**
- * Maximum allowed message size in bytes {@link DefaultMQProducer#maxMessageSize}.
- */
- private Integer maxMessageSize = 1024 * 1024 * 4;
-
- private Boolean transactional = false;
-
- private Boolean sync = false;
-
- private Boolean vipChannelEnabled = true;
-
- /**
- * Millis of send message timeout.
- */
- private int sendMessageTimeout = 3000;
+ private int sendMsgTimeout = 3000;
/**
* Compress message body threshold, namely, message body larger than 4k will be
* compressed on default.
*/
- private int compressMessageBodyThreshold = 1024 * 4;
+ private int compressMsgBodyThreshold = 1024 * 4;
/**
* Maximum number of retry to perform internally before claiming sending failure in
- * synchronous mode. This may potentially cause message duplication which is up to
- * application developers to resolve.
+ * synchronous mode.
+ *
+ *
+ * This may potentially cause message duplication which is up to application
+ * developers to resolve.
*/
private int retryTimesWhenSendFailed = 2;
/**
- *
* Maximum number of retry to perform internally before claiming sending failure in
* asynchronous mode.
*
+ *
* This may potentially cause message duplication which is up to application
* developers to resolve.
*/
@@ -73,94 +57,165 @@ public class RocketMQProducerProperties {
/**
* Indicate whether to retry another broker on sending failure internally.
*/
- private boolean retryNextServer = false;
+ private boolean retryAnotherBroker = false;
- public String getGroup() {
- return group;
+ /**
+ * Maximum allowed message size in bytes.
+ */
+ private int maxMessageSize = 1024 * 1024 * 4;
+
+ private String producerType = ProducerType.Normal.name();
+
+ private String sendType = SendType.Sync.name();
+
+ private String sendCallBack;
+
+ private String transactionListener;
+
+ private String messageQueueSelector;
+
+ private String errorMessageStrategy;
+
+ private String sendFailureChannel;
+
+ private String checkForbiddenHook;
+
+ private String sendMessageHook;
+
+ public int getSendMsgTimeout() {
+ return sendMsgTimeout;
+ }
+
+ public void setSendMsgTimeout(int sendMsgTimeout) {
+ this.sendMsgTimeout = sendMsgTimeout;
}
- public void setGroup(String group) {
- this.group = group;
+ public int getCompressMsgBodyThreshold() {
+ return compressMsgBodyThreshold;
}
- public Boolean getEnabled() {
- return enabled;
+ public void setCompressMsgBodyThreshold(int compressMsgBodyThreshold) {
+ this.compressMsgBodyThreshold = compressMsgBodyThreshold;
}
- public void setEnabled(Boolean enabled) {
- this.enabled = enabled;
+ public int getRetryTimesWhenSendFailed() {
+ return retryTimesWhenSendFailed;
}
- public Integer getMaxMessageSize() {
+ public void setRetryTimesWhenSendFailed(int retryTimesWhenSendFailed) {
+ this.retryTimesWhenSendFailed = retryTimesWhenSendFailed;
+ }
+
+ public int getRetryTimesWhenSendAsyncFailed() {
+ return retryTimesWhenSendAsyncFailed;
+ }
+
+ public void setRetryTimesWhenSendAsyncFailed(int retryTimesWhenSendAsyncFailed) {
+ this.retryTimesWhenSendAsyncFailed = retryTimesWhenSendAsyncFailed;
+ }
+
+ public boolean getRetryAnotherBroker() {
+ return retryAnotherBroker;
+ }
+
+ public void setRetryAnotherBroker(boolean retryAnotherBroker) {
+ this.retryAnotherBroker = retryAnotherBroker;
+ }
+
+ public int getMaxMessageSize() {
return maxMessageSize;
}
- public void setMaxMessageSize(Integer maxMessageSize) {
+ public void setMaxMessageSize(int maxMessageSize) {
this.maxMessageSize = maxMessageSize;
}
- public Boolean getTransactional() {
- return transactional;
+ public String getProducerType() {
+ return producerType;
}
- public void setTransactional(Boolean transactional) {
- this.transactional = transactional;
+ public void setProducerType(String producerType) {
+ this.producerType = producerType;
}
- public Boolean getSync() {
- return sync;
+ public String getSendType() {
+ return sendType;
}
- public void setSync(Boolean sync) {
- this.sync = sync;
+ public void setSendType(String sendType) {
+ this.sendType = sendType;
}
- public Boolean getVipChannelEnabled() {
- return vipChannelEnabled;
+ public String getSendCallBack() {
+ return sendCallBack;
}
- public void setVipChannelEnabled(Boolean vipChannelEnabled) {
- this.vipChannelEnabled = vipChannelEnabled;
+ public void setSendCallBack(String sendCallBack) {
+ this.sendCallBack = sendCallBack;
}
- public int getSendMessageTimeout() {
- return sendMessageTimeout;
+ public String getTransactionListener() {
+ return transactionListener;
}
- public void setSendMessageTimeout(int sendMessageTimeout) {
- this.sendMessageTimeout = sendMessageTimeout;
+ public void setTransactionListener(String transactionListener) {
+ this.transactionListener = transactionListener;
}
- public int getCompressMessageBodyThreshold() {
- return compressMessageBodyThreshold;
+ public String getMessageQueueSelector() {
+ return messageQueueSelector;
}
- public void setCompressMessageBodyThreshold(int compressMessageBodyThreshold) {
- this.compressMessageBodyThreshold = compressMessageBodyThreshold;
+ public void setMessageQueueSelector(String messageQueueSelector) {
+ this.messageQueueSelector = messageQueueSelector;
}
- public int getRetryTimesWhenSendFailed() {
- return retryTimesWhenSendFailed;
+ public String getErrorMessageStrategy() {
+ return errorMessageStrategy;
}
- public void setRetryTimesWhenSendFailed(int retryTimesWhenSendFailed) {
- this.retryTimesWhenSendFailed = retryTimesWhenSendFailed;
+ public void setErrorMessageStrategy(String errorMessageStrategy) {
+ this.errorMessageStrategy = errorMessageStrategy;
}
- public int getRetryTimesWhenSendAsyncFailed() {
- return retryTimesWhenSendAsyncFailed;
+ public String getSendFailureChannel() {
+ return sendFailureChannel;
}
- public void setRetryTimesWhenSendAsyncFailed(int retryTimesWhenSendAsyncFailed) {
- this.retryTimesWhenSendAsyncFailed = retryTimesWhenSendAsyncFailed;
+ public void setSendFailureChannel(String sendFailureChannel) {
+ this.sendFailureChannel = sendFailureChannel;
+ }
+
+ public String getCheckForbiddenHook() {
+ return checkForbiddenHook;
}
- public boolean isRetryNextServer() {
- return retryNextServer;
+ public void setCheckForbiddenHook(String checkForbiddenHook) {
+ this.checkForbiddenHook = checkForbiddenHook;
}
- public void setRetryNextServer(boolean retryNextServer) {
- this.retryNextServer = retryNextServer;
+ public String getSendMessageHook() {
+ return sendMessageHook;
+ }
+
+ public void setSendMessageHook(String sendMessageHook) {
+ this.sendMessageHook = sendMessageHook;
+ }
+
+ public enum ProducerType {
+ Normal, Trans;
+
+ public boolean equalsName(String name) {
+ return this.name().equalsIgnoreCase(name);
+ }
+ }
+
+ public enum SendType {
+ OneWay, Async, Sync,;
+
+ public boolean equalsName(String name) {
+ return this.name().equalsIgnoreCase(name);
+ }
}
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java
index 694dcdc96b..0580fe8591 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/provisioning/selector/PartitionMessageQueueSelector.java
@@ -36,7 +36,7 @@ public class PartitionMessageQueueSelector implements MessageQueueSelector {
@Override
public MessageQueue select(List mqs, Message msg, Object arg) {
- Integer partition = 0;
+ int partition = 0;
try {
partition = Math.abs(
Integer.parseInt(msg.getProperty(BinderHeaders.PARTITION_HEADER)));
From a6e01c998417669fcd4d4b053db454d37725fe7a Mon Sep 17 00:00:00 2001
From: zkzlx
Date: Mon, 1 Feb 2021 11:24:25 +0800
Subject: [PATCH 02/19] Code refactoring and some new feature support
---
...gHandlerMappingsProviderConfiguration.java | 45 +++
.../RocketMQBinderAutoConfiguration.java | 81 +++++
.../rocketmq/contants/RocketMQConst.java | 90 ++++++
.../convert/RocketMQMessageConverter.java | 84 +++++
.../custom/RocketMQBeanContainerCache.java | 75 +++++
.../RocketMQConfigBeanPostProcessor.java | 43 +++
.../extend/ErrorAcknowledgeHandler.java | 35 +++
.../inbound/RocketMQConsumerFactory.java | 156 ++++++++++
.../RocketMQInboundChannelAdapter.java | 228 ++++++++++++++
.../pull/DefaultErrorAcknowledgeHandler.java | 43 +++
.../inbound/pull/RocketMQAckCallback.java | 112 +++++++
.../inbound/pull/RocketMQMessageSource.java | 161 ++++++++++
.../outbound/RocketMQProduceFactory.java | 131 ++++++++
.../RocketMQProducerMessageHandler.java | 286 ++++++++++++++++++
.../properties/RocketMQCommonProperties.java | 201 ++++++++++++
.../RocketMQSpecificPropertiesProvider.java | 66 ++++
.../RocketMQMessageConverterSupport.java | 185 +++++++++++
.../binder/rocketmq/utils/RocketMQUtils.java | 98 ++++++
18 files changed, 2120 insertions(+)
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java
create mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java
new file mode 100644
index 0000000000..eb6e6ce520
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/ExtendedBindingHandlerMappingsProviderConfiguration.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013-2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://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 com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
+import org.springframework.cloud.stream.config.BindingHandlerAdvise.MappingsProvider;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ExtendedBindingHandlerMappingsProviderConfiguration {
+
+ @Bean
+ public MappingsProvider rocketExtendedPropertiesDefaultMappingsProvider() {
+ return () -> {
+ Map mappings = new HashMap<>();
+ mappings.put(
+ ConfigurationPropertyName.of("spring.cloud.stream.rocketmq.bindings"),
+ ConfigurationPropertyName.of("spring.cloud.stream.rocketmq.default"));
+ mappings.put(
+ ConfigurationPropertyName.of("spring.cloud.stream.rocketmq.streams"),
+ ConfigurationPropertyName
+ .of("spring.cloud.stream.rocketmq.streams.default"));
+ return mappings;
+ };
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java
new file mode 100644
index 0000000000..abcb9b961a
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2013-2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://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 com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate;
+
+import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder;
+import com.alibaba.cloud.stream.binder.rocketmq.actuator.RocketMQBinderHealthIndicator;
+import com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter;
+import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQConfigBeanPostProcessor;
+import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;
+import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties;
+import com.alibaba.cloud.stream.binder.rocketmq.provisioning.RocketMQTopicProvisioner;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.messaging.converter.CompositeMessageConverter;
+
+/**
+ * issue:https://github.com/alibaba/spring-cloud-alibaba/issues/1681
+ * @author Timur Valiev
+ * @author Jim
+ */
+@Configuration(proxyBeanMethods = false)
+@EnableConfigurationProperties({ RocketMQExtendedBindingProperties.class,
+ RocketMQBinderConfigurationProperties.class })
+public class RocketMQBinderAutoConfiguration {
+
+ @Autowired
+ private RocketMQExtendedBindingProperties extendedBindingProperties;
+ @Autowired
+ private RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties;
+
+ @Bean
+ public RocketMQConfigBeanPostProcessor rocketMQConfigBeanPostProcessor() {
+ return new RocketMQConfigBeanPostProcessor();
+ }
+
+ @Bean(RocketMQMessageConverter.DEFAULT_NAME)
+ @ConditionalOnMissingBean(name = { RocketMQMessageConverter.DEFAULT_NAME })
+ public CompositeMessageConverter rocketMQMessageConverter() {
+ return new RocketMQMessageConverter().getMessageConverter();
+ }
+
+ @Bean
+ @ConditionalOnEnabledHealthIndicator("rocketmq")
+ @ConditionalOnClass(name = "org.springframework.boot.actuate.health.HealthIndicator")
+ public RocketMQBinderHealthIndicator rocketMQBinderHealthIndicator() {
+ return new RocketMQBinderHealthIndicator();
+ }
+
+ @Bean
+ public RocketMQTopicProvisioner rocketMQTopicProvisioner() {
+ return new RocketMQTopicProvisioner();
+ }
+
+ @Bean
+ public RocketMQMessageChannelBinder rocketMQMessageChannelBinder(
+ RocketMQTopicProvisioner provisioningProvider) {
+ return new RocketMQMessageChannelBinder(rocketBinderConfigurationProperties,
+ extendedBindingProperties, provisioningProvider);
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java
new file mode 100644
index 0000000000..e83a6a172e
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.contants;
+
+import org.apache.rocketmq.common.message.MessageConst;
+
+import static org.apache.rocketmq.spring.support.RocketMQHeaders.PREFIX;
+
+/**
+ * @author zkzlx
+ */
+public class RocketMQConst extends MessageConst {
+
+ /**
+ * Header key for RocketMQ Transactional Args.
+ */
+ public static final String ROCKET_TRANSACTIONAL_ARG = "TRANSACTIONAL_ARG";
+
+ /**
+ * Default NameServer value.
+ */
+ public static final String DEFAULT_NAME_SERVER = "127.0.0.1:9876";
+
+ /**
+ * Default group for SCS RocketMQ Binder.
+ */
+ public static final String DEFAULT_GROUP = PREFIX + "binder_default_group_name";
+
+ /**
+ * RocketMQ re-consume times.
+ */
+ public static final String ROCKETMQ_RECONSUME_TIMES = PREFIX + "RECONSUME_TIMES";
+
+ public static final String USER_TRANSACTIONAL_ARGS = "TRANSACTIONAL_ARGS";
+
+ /**
+ * It is mainly provided for conversion between rocketMq-message and Spring-message,
+ * and parameters are passed through HEADERS.
+ */
+ public static class Headers {
+ public static final String KEYS = MessageConst.PROPERTY_KEYS;
+ public static final String TAGS = MessageConst.PROPERTY_TAGS;
+ public static final String TOPIC = "MQ_TOPIC";
+ /**
+ * The ID of the message.
+ */
+ public static final String MESSAGE_ID = "MQ_MESSAGE_ID";
+ /**
+ * The timestamp that the message producer invokes the message sending API.
+ */
+ public static final String BORN_TIMESTAMP = "MQ_BORN_TIMESTAMP";
+ /**
+ * The IP and port number of the message producer
+ */
+ public static final String BORN_HOST = "MQ_BORN_HOST";
+
+ /**
+ * Message flag, MQ is not processed and is available for use by applications.
+ */
+ public static final String FLAG = "MQ_FLAG";
+ /**
+ * Message consumption queue ID
+ */
+ public static final String QUEUE_ID = "MQ_QUEUE_ID";
+ /**
+ * Message system Flag, such as whether or not to compress, whether or not to
+ * transactional messages.
+ */
+ public static final String SYS_FLAG = "MQ_SYS_FLAG";
+ /**
+ * The transaction ID of the transaction message.
+ */
+ public static final String TRANSACTION_ID = "MQ_TRANSACTION_ID";
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java
new file mode 100644
index 0000000000..58f17c6efc
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.convert;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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;
+
+/**
+ * The default message converter of rocketMq,its bean name is {@link #DEFAULT_NAME}
+ * @author zkzlx
+ */
+public class RocketMQMessageConverter {
+
+ public static final String DEFAULT_NAME = "rocketMQMessageConverter";
+
+ 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 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 ignored) {
+ // ignore this exception
+ }
+ }
+ messageConverter = new CompositeMessageConverter(messageConverters);
+ }
+
+ public CompositeMessageConverter getMessageConverter() {
+ return messageConverter;
+ }
+
+ public void setMessageConverter(CompositeMessageConverter messageConverter) {
+ this.messageConverter = messageConverter;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java
new file mode 100644
index 0000000000..9afc948212
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.custom;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.alibaba.cloud.stream.binder.rocketmq.extend.ErrorAcknowledgeHandler;
+import org.apache.rocketmq.client.consumer.AllocateMessageQueueStrategy;
+import org.apache.rocketmq.client.consumer.listener.MessageListener;
+import org.apache.rocketmq.client.hook.CheckForbiddenHook;
+import org.apache.rocketmq.client.hook.SendMessageHook;
+import org.apache.rocketmq.client.producer.MessageQueueSelector;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.TransactionListener;
+
+import org.springframework.messaging.converter.CompositeMessageConverter;
+import org.springframework.util.StringUtils;
+
+/**
+ * Gets the beans configured in the configuration file
+ *
+ * @author junboXiang
+ */
+public final class RocketMQBeanContainerCache {
+
+ private static final Class>[] CLASSES = new Class[] {
+ CompositeMessageConverter.class, AllocateMessageQueueStrategy.class,
+ MessageQueueSelector.class, MessageListener.class, TransactionListener.class,
+ SendCallback.class, CheckForbiddenHook.class, SendMessageHook.class,
+ ErrorAcknowledgeHandler.class };
+
+ private static final Map BEANS_CACHE = new ConcurrentHashMap<>();
+
+ static void putBean(String beanName, Object beanObj) {
+ BEANS_CACHE.put(beanName, beanObj);
+ }
+
+ static Class>[] getClassAry() {
+ return CLASSES;
+ }
+
+ public static T getBean(String beanName, Class clazz) {
+ return getBean(beanName, clazz, null);
+ }
+
+ public static T getBean(String beanName, Class clazz, T defaultObj) {
+ if (StringUtils.isEmpty(beanName)) {
+ return defaultObj;
+ }
+ Object obj = BEANS_CACHE.get(beanName);
+ if (null == obj) {
+ return defaultObj;
+ }
+ if (clazz.isAssignableFrom(obj.getClass())) {
+ return (T) obj;
+ }
+ return defaultObj;
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java
new file mode 100644
index 0000000000..30bd643283
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.custom;
+
+import java.util.stream.Stream;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+
+/**
+ * find RocketMQ bean by annotations
+ *
+ * @author junboXiang
+ *
+ */
+public class RocketMQConfigBeanPostProcessor implements BeanPostProcessor {
+
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName)
+ throws BeansException {
+ Stream.of(RocketMQBeanContainerCache.getClassAry()).forEach(clazz -> {
+ if (clazz.isAssignableFrom(bean.getClass())) {
+ RocketMQBeanContainerCache.putBean(beanName, bean);
+ }
+ });
+ return bean;
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java
new file mode 100644
index 0000000000..fcf6de8045
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.extend;
+
+import org.springframework.integration.acks.AcknowledgmentCallback.Status;
+import org.springframework.messaging.Message;
+
+/**
+ * @author zkzlx
+ */
+public interface ErrorAcknowledgeHandler {
+
+ /**
+ * Ack state handling, including receive, reject, and retry, when a consumption
+ * exception occurs.
+ * @param message
+ * @return see {@link Status}
+ */
+ Status handler(Message> message);
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java
new file mode 100644
index 0000000000..876249581f
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2013-2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://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 com.alibaba.cloud.stream.binder.rocketmq.integration.inbound;
+
+import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache;
+import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;
+import com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils;
+import org.apache.rocketmq.acl.common.AclClientRPCHook;
+import org.apache.rocketmq.acl.common.SessionCredentials;
+import org.apache.rocketmq.client.consumer.AllocateMessageQueueStrategy;
+import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer;
+import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
+import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely;
+import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
+import org.apache.rocketmq.remoting.RPCHook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.cloud.stream.binder.ExtendedConsumerProperties;
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
+/**
+ * Extended function related to producer . eg:initial
+ *
+ * @author zkzlx
+ */
+public final class RocketMQConsumerFactory {
+
+ private final static Logger log = LoggerFactory
+ .getLogger(RocketMQConsumerFactory.class);
+
+ public static DefaultMQPushConsumer initPushConsumer(
+ ExtendedConsumerProperties extendedConsumerProperties) {
+ RocketMQConsumerProperties consumerProperties = extendedConsumerProperties
+ .getExtension();
+ Assert.notNull(consumerProperties.getGroup(),
+ "Property 'group' is required - consumerGroup");
+ Assert.notNull(consumerProperties.getNameServer(),
+ "Property 'nameServer' is required");
+ AllocateMessageQueueStrategy allocateMessageQueueStrategy = RocketMQBeanContainerCache
+ .getBean(consumerProperties.getAllocateMessageQueueStrategy(),
+ AllocateMessageQueueStrategy.class,
+ new AllocateMessageQueueAveragely());
+ RPCHook rpcHook = null;
+ if (!StringUtils.isEmpty(consumerProperties.getAccessKey())
+ && !StringUtils.isEmpty(consumerProperties.getSecretKey())) {
+ rpcHook = new AclClientRPCHook(
+ new SessionCredentials(consumerProperties.getAccessKey(),
+ consumerProperties.getSecretKey()));
+ }
+ DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(
+ consumerProperties.getGroup(), rpcHook, allocateMessageQueueStrategy,
+ consumerProperties.getEnableMsgTrace(),
+ consumerProperties.getCustomizedTraceTopic());
+ consumer.setVipChannelEnabled(
+ null == rpcHook && consumerProperties.getVipChannelEnabled());
+ consumer.setInstanceName(
+ RocketMQUtils.getInstanceName(rpcHook, consumerProperties.getGroup()));
+ consumer.setNamespace(consumerProperties.getNamespace());
+ consumer.setNamesrvAddr(consumerProperties.getNameServer());
+ consumer.setMessageModel(getMessageModel(consumerProperties.getMessageModel()));
+ consumer.setUseTLS(consumerProperties.getUseTLS());
+ consumer.setPullTimeDelayMillsWhenException(
+ consumerProperties.getPullTimeDelayMillsWhenException());
+ consumer.setPullBatchSize(consumerProperties.getPullBatchSize());
+ consumer.setConsumeFromWhere(consumerProperties.getConsumeFromWhere());
+ consumer.setHeartbeatBrokerInterval(
+ consumerProperties.getHeartbeatBrokerInterval());
+ consumer.setPersistConsumerOffsetInterval(
+ consumerProperties.getPersistConsumerOffsetInterval());
+ consumer.setPullInterval(consumerProperties.getPush().getPullInterval());
+ consumer.setConsumeThreadMin(extendedConsumerProperties.getConcurrency());
+ consumer.setConsumeThreadMax(extendedConsumerProperties.getConcurrency());
+ return consumer;
+ }
+
+ /**
+ * todo Compatible with versions less than 4.6 ?
+ * @return
+ */
+ public static DefaultLitePullConsumer initPullConsumer(
+ ExtendedConsumerProperties extendedConsumerProperties) {
+ RocketMQConsumerProperties consumerProperties = extendedConsumerProperties
+ .getExtension();
+ Assert.notNull(consumerProperties.getGroup(),
+ "Property 'group' is required - consumerGroup");
+ Assert.notNull(consumerProperties.getNameServer(),
+ "Property 'nameServer' is required");
+ AllocateMessageQueueStrategy allocateMessageQueueStrategy = RocketMQBeanContainerCache
+ .getBean(consumerProperties.getAllocateMessageQueueStrategy(),
+ AllocateMessageQueueStrategy.class,
+ new AllocateMessageQueueAveragely());
+
+ RPCHook rpcHook = null;
+ if (!StringUtils.isEmpty(consumerProperties.getAccessKey())
+ && !StringUtils.isEmpty(consumerProperties.getSecretKey())) {
+ rpcHook = new AclClientRPCHook(
+ new SessionCredentials(consumerProperties.getAccessKey(),
+ consumerProperties.getSecretKey()));
+ }
+
+ DefaultLitePullConsumer consumer = new DefaultLitePullConsumer(
+ consumerProperties.getNamespace(), consumerProperties.getGroup(),
+ rpcHook);
+ consumer.setVipChannelEnabled(
+ null == rpcHook && consumerProperties.getVipChannelEnabled());
+ consumer.setInstanceName(
+ RocketMQUtils.getInstanceName(rpcHook, consumerProperties.getGroup()));
+ consumer.setAllocateMessageQueueStrategy(allocateMessageQueueStrategy);
+ consumer.setNamesrvAddr(consumerProperties.getNameServer());
+ consumer.setMessageModel(getMessageModel(consumerProperties.getMessageModel()));
+ consumer.setUseTLS(consumerProperties.getUseTLS());
+ consumer.setPullTimeDelayMillsWhenException(
+ consumerProperties.getPullTimeDelayMillsWhenException());
+ consumer.setConsumerTimeoutMillisWhenSuspend(
+ consumerProperties.getPull().getConsumerTimeoutMillisWhenSuspend());
+ consumer.setPullBatchSize(consumerProperties.getPullBatchSize());
+ consumer.setConsumeFromWhere(consumerProperties.getConsumeFromWhere());
+ consumer.setHeartbeatBrokerInterval(
+ consumerProperties.getHeartbeatBrokerInterval());
+ consumer.setPersistConsumerOffsetInterval(
+ consumerProperties.getPersistConsumerOffsetInterval());
+ consumer.setPollTimeoutMillis(
+ consumerProperties.getPull().getPollTimeoutMillis());
+ consumer.setPullThreadNums(extendedConsumerProperties.getConcurrency());
+ // The internal queues are cached by a maximum of 1000
+ consumer.setPullThresholdForAll(extendedConsumerProperties.getExtension()
+ .getPull().getPullThresholdForAll());
+ return consumer;
+ }
+
+ private static MessageModel getMessageModel(String messageModel) {
+ for (MessageModel model : MessageModel.values()) {
+ if (model.getModeCN().equalsIgnoreCase(messageModel)) {
+ return model;
+ }
+ }
+ return MessageModel.CLUSTERING;
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java
new file mode 100644
index 0000000000..d0aec55237
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2013-2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://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 com.alibaba.cloud.stream.binder.rocketmq.integration.inbound;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation;
+import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager;
+import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;
+import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQMessageConverterSupport;
+import com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils;
+import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
+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.common.message.MessageExt;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.cloud.stream.binder.ExtendedConsumerProperties;
+import org.springframework.integration.context.OrderlyShutdownCapable;
+import org.springframework.integration.endpoint.MessageProducerSupport;
+import org.springframework.integration.support.MessageBuilder;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessagingException;
+import org.springframework.retry.RecoveryCallback;
+import org.springframework.retry.RetryCallback;
+import org.springframework.retry.RetryContext;
+import org.springframework.retry.RetryListener;
+import org.springframework.retry.support.RetryTemplate;
+import org.springframework.util.Assert;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * TODO Describe what it does
+ * @author Jim
+ */
+public class RocketMQInboundChannelAdapter extends MessageProducerSupport
+ implements OrderlyShutdownCapable {
+
+ private static final Logger log = LoggerFactory
+ .getLogger(RocketMQInboundChannelAdapter.class);
+
+ private RetryTemplate retryTemplate;
+ private RecoveryCallback recoveryCallback;
+ private DefaultMQPushConsumer pushConsumer;
+
+ private final String topic;
+ private final ExtendedConsumerProperties extendedConsumerProperties;
+
+ public RocketMQInboundChannelAdapter(String topic,
+ ExtendedConsumerProperties extendedConsumerProperties) {
+ this.topic = topic;
+ this.extendedConsumerProperties = extendedConsumerProperties;
+ }
+
+ @Override
+ protected void onInit() {
+ if (extendedConsumerProperties.getExtension() == null
+ || !extendedConsumerProperties.getExtension().getEnabled()) {
+ return;
+ }
+ Instrumentation instrumentation = new Instrumentation(topic, this);
+ try {
+ super.onInit();
+ if (this.retryTemplate != null) {
+ Assert.state(getErrorChannel() == null,
+ "Cannot have an 'errorChannel' property when a 'RetryTemplate' is "
+ + "provided; use an 'ErrorMessageSendingRecoverer' in the 'recoveryCallback' property to "
+ + "send an error message when retries are exhausted");
+ this.retryTemplate.registerListener(new RetryListener() {
+ @Override
+ public boolean open(RetryContext context,
+ RetryCallback callback) {
+ return true;
+ }
+
+ @Override
+ public void close(RetryContext context,
+ RetryCallback callback, Throwable throwable) {
+ }
+
+ @Override
+ public void onError(RetryContext context,
+ RetryCallback callback, Throwable throwable) {
+ }
+ });
+ }
+ pushConsumer = RocketMQConsumerFactory
+ .initPushConsumer(extendedConsumerProperties);
+ // prepare register consumer message listener,the next step is to be
+ // compatible with a custom MessageListener.
+ if (extendedConsumerProperties.getExtension().getPush().getOrderly()) {
+ pushConsumer.registerMessageListener((MessageListenerOrderly) (msgs,
+ context) -> RocketMQInboundChannelAdapter.this
+ .consumeMessage(msgs, () -> {
+ context.setSuspendCurrentQueueTimeMillis(
+ extendedConsumerProperties.getExtension()
+ .getPush()
+ .getSuspendCurrentQueueTimeMillis());
+ return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;
+ }, () -> ConsumeOrderlyStatus.SUCCESS));
+ }
+ else {
+ pushConsumer.registerMessageListener((MessageListenerConcurrently) (msgs,
+ context) -> RocketMQInboundChannelAdapter.this
+ .consumeMessage(msgs, () -> {
+ context.setDelayLevelWhenNextConsume(
+ extendedConsumerProperties.getExtension()
+ .getPush()
+ .getDelayLevelWhenNextConsume());
+ return ConsumeConcurrentlyStatus.RECONSUME_LATER;
+ }, () -> ConsumeConcurrentlyStatus.CONSUME_SUCCESS));
+ }
+ instrumentation.markStartedSuccessfully();
+ }
+ catch (Exception e) {
+ instrumentation.markStartFailed(e);
+ log.error("DefaultMQPushConsumer init failed, Caused by " + e.getMessage());
+ throw new MessagingException(MessageBuilder.withPayload(
+ "DefaultMQPushConsumer init failed, Caused by " + e.getMessage())
+ .build(), e);
+ }
+ finally {
+ InstrumentationManager.addHealthInstrumentation(instrumentation);
+ }
+ }
+
+ /**
+ * The actual execution of a user-defined input consumption service method.
+ * @param messageExtList rocket mq message list
+ * @param failSupplier {@link ConsumeConcurrentlyStatus} or
+ * {@link ConsumeOrderlyStatus}
+ * @param sucSupplier {@link ConsumeConcurrentlyStatus} or
+ * {@link ConsumeOrderlyStatus}
+ * @param
+ * @return
+ */
+ private R consumeMessage(List messageExtList,
+ Supplier failSupplier, Supplier sucSupplier) {
+ if (CollectionUtils.isEmpty(messageExtList)) {
+ throw new MessagingException(
+ "DefaultMQPushConsumer consuming failed, Caused by messageExtList is empty");
+ }
+ for (MessageExt messageExt : messageExtList) {
+ try {
+ Message> message = RocketMQMessageConverterSupport
+ .convertMessage2Spring(messageExt);
+ if (this.retryTemplate != null) {
+ this.retryTemplate.execute(context -> {
+ this.sendMessage(message);
+ return message;
+ }, this.recoveryCallback);
+ }
+ else {
+ this.sendMessage(message);
+ }
+ }
+ catch (Exception e) {
+ log.warn("consume message failed. messageExt:{}", messageExt, e);
+ return failSupplier.get();
+ }
+ }
+ return sucSupplier.get();
+ }
+
+ @Override
+ protected void doStart() {
+ if (extendedConsumerProperties.getExtension() == null
+ || !extendedConsumerProperties.getExtension().getEnabled()) {
+ return;
+ }
+ try {
+ pushConsumer.subscribe(topic, RocketMQUtils.getMessageSelector(
+ extendedConsumerProperties.getExtension().getSubscription()));
+ pushConsumer.start();
+ }
+ catch (Exception e) {
+ log.error("DefaultMQPushConsumer init failed, Caused by " + e.getMessage());
+ throw new MessagingException(MessageBuilder.withPayload(
+ "DefaultMQPushConsumer init failed, Caused by " + e.getMessage())
+ .build(), e);
+ }
+ }
+
+ @Override
+ protected void doStop() {
+ if (pushConsumer != null) {
+ pushConsumer.shutdown();
+ }
+ }
+
+ public void setRetryTemplate(RetryTemplate retryTemplate) {
+ this.retryTemplate = retryTemplate;
+ }
+
+ public void setRecoveryCallback(RecoveryCallback recoveryCallback) {
+ this.recoveryCallback = recoveryCallback;
+ }
+
+ @Override
+ public int beforeShutdown() {
+ this.stop();
+ return 0;
+ }
+
+ @Override
+ public int afterShutdown() {
+ return 0;
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java
new file mode 100644
index 0000000000..3296a128e9
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull;
+
+import com.alibaba.cloud.stream.binder.rocketmq.extend.ErrorAcknowledgeHandler;
+
+import org.springframework.integration.acks.AcknowledgmentCallback.Status;
+import org.springframework.messaging.Message;
+
+/**
+ * By default, if consumption fails, the corresponding MessageQueue will always be
+ * retried, that is, the consumption of other messages in the MessageQueue will be
+ * blocked.
+ *
+ * @author zkzlx
+ */
+public class DefaultErrorAcknowledgeHandler implements ErrorAcknowledgeHandler {
+ /**
+ * Ack state handling, including receive, reject, and retry, when a consumption
+ * exception occurs.
+ *
+ * @param message
+ * @return see {@link Status}
+ */
+ @Override
+ public Status handler(Message> message) {
+ return Status.REQUEUE;
+ }
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java
new file mode 100644
index 0000000000..f617dd097e
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull;
+
+import org.apache.rocketmq.client.consumer.DefaultLitePullConsumer;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.impl.consumer.AssignedMessageQueue;
+import org.apache.rocketmq.client.impl.consumer.ProcessQueue;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.message.MessageQueue;
+import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.integration.acks.AcknowledgmentCallback;
+import org.springframework.util.Assert;
+
+/**
+ * A pollable {@link org.springframework.integration.core.MessageSource} for RocketMQ.
+ * @author zkzlx
+ */
+public class RocketMQAckCallback implements AcknowledgmentCallback {
+ private final static Logger log = LoggerFactory.getLogger(RocketMQAckCallback.class);
+
+ private boolean acknowledged;
+ private boolean autoAckEnabled = true;
+ private MessageExt messageExt;
+ private AssignedMessageQueue assignedMessageQueue;
+ private DefaultLitePullConsumer consumer;
+ private final MessageQueue messageQueue;
+
+ public RocketMQAckCallback(DefaultLitePullConsumer consumer,
+ AssignedMessageQueue assignedMessageQueue, MessageQueue messageQueue,
+ MessageExt messageExt) {
+ this.messageExt = messageExt;
+ this.consumer = consumer;
+ this.assignedMessageQueue = assignedMessageQueue;
+ this.messageQueue = messageQueue;
+ }
+
+ @Override
+ public boolean isAcknowledged() {
+ return this.acknowledged;
+ }
+
+ @Override
+ public void noAutoAck() {
+ this.autoAckEnabled = false;
+ }
+
+ @Override
+ public boolean isAutoAck() {
+ return this.autoAckEnabled;
+ }
+
+ @Override
+ public void acknowledge(Status status) {
+ Assert.notNull(status, "'status' cannot be null");
+ if (this.acknowledged) {
+ throw new IllegalStateException("Already acknowledged");
+ }
+ synchronized (messageQueue) {
+ try {
+ long offset = messageExt.getQueueOffset();
+ switch (status) {
+ case REJECT:
+ case ACCEPT:
+ long consumerOffset = assignedMessageQueue
+ .getConsumerOffset(messageQueue);
+ if (consumerOffset != -1) {
+ ProcessQueue processQueue = assignedMessageQueue
+ .getProcessQueue(messageQueue);
+ if (processQueue != null && !processQueue.isDropped()) {
+ consumer.getOffsetStore().updateOffset(messageQueue,
+ consumerOffset, false);
+ }
+ }
+ if (consumer.getMessageModel() == MessageModel.BROADCASTING) {
+ consumer.getOffsetStore().persist(messageQueue);
+ }
+ break;
+ case REQUEUE:
+ consumer.seek(messageQueue, offset);
+ break;
+ default:
+ break;
+ }
+ }
+ catch (MQClientException e) {
+ throw new IllegalStateException(e);
+ }
+ finally {
+ this.acknowledged = true;
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java
new file mode 100644
index 0000000000..2ca91384b0
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2013-2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://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 com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+import com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.RocketMQConsumerFactory;
+import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation;
+import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager;
+import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;
+import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQMessageConverterSupport;
+import com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils;
+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.impl.consumer.AssignedMessageQueue;
+import org.apache.rocketmq.client.impl.consumer.DefaultLitePullConsumerImpl;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.message.MessageQueue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.cloud.stream.binder.ExtendedConsumerProperties;
+import org.springframework.context.Lifecycle;
+import org.springframework.integration.IntegrationMessageHeaderAccessor;
+import org.springframework.integration.endpoint.AbstractMessageSource;
+import org.springframework.integration.support.MessageBuilder;
+import org.springframework.messaging.Message;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ReflectionUtils;
+
+/**
+ * @author Jim
+ */
+public class RocketMQMessageSource extends AbstractMessageSource
+ implements DisposableBean, Lifecycle {
+
+ private final static Logger log = LoggerFactory
+ .getLogger(RocketMQMessageSource.class);
+
+ private DefaultLitePullConsumer consumer;
+ private AssignedMessageQueue assignedMessageQueue;
+ private volatile boolean running;
+
+ private final String topic;
+ private final MessageSelector messageSelector;
+ private final ExtendedConsumerProperties extendedConsumerProperties;
+
+ public RocketMQMessageSource(String name,
+ ExtendedConsumerProperties extendedConsumerProperties) {
+ this.topic = name;
+ this.messageSelector = RocketMQUtils.getMessageSelector(
+ extendedConsumerProperties.getExtension().getSubscription());
+ this.extendedConsumerProperties = extendedConsumerProperties;
+
+ }
+
+ @Override
+ public synchronized void start() {
+ Instrumentation instrumentation = new Instrumentation(topic, this);
+ try {
+ if (this.isRunning()) {
+ throw new IllegalStateException(
+ "pull consumer already running. " + this.toString());
+ }
+ this.consumer = RocketMQConsumerFactory
+ .initPullConsumer(extendedConsumerProperties);
+ // This parameter must be 1, otherwise doReceive cannot be handled singly.
+ this.consumer.setPullBatchSize(1);
+ this.consumer.subscribe(topic, messageSelector);
+ this.consumer.setAutoCommit(false);
+ this.assignedMessageQueue = acquireAssignedMessageQueue(this.consumer);
+ this.consumer.start();
+ instrumentation.markStartedSuccessfully();
+ }
+ catch (MQClientException e) {
+ instrumentation.markStartFailed(e);
+ log.error("DefaultMQPullConsumer startup error: " + e.getMessage(), e);
+ }
+ finally {
+ InstrumentationManager.addHealthInstrumentation(instrumentation);
+ }
+ this.running = true;
+ }
+
+ private AssignedMessageQueue acquireAssignedMessageQueue(
+ DefaultLitePullConsumer consumer) {
+ Field field = ReflectionUtils.findField(DefaultLitePullConsumer.class,
+ "defaultLitePullConsumerImpl");
+ assert field != null;
+ field.setAccessible(true);
+ DefaultLitePullConsumerImpl defaultLitePullConsumerImpl = (DefaultLitePullConsumerImpl) ReflectionUtils
+ .getField(field, consumer);
+
+ field = ReflectionUtils.findField(DefaultLitePullConsumerImpl.class,
+ "assignedMessageQueue");
+ assert field != null;
+ field.setAccessible(true);
+ return (AssignedMessageQueue) ReflectionUtils.getField(field,
+ defaultLitePullConsumerImpl);
+ }
+
+ @Override
+ public synchronized void stop() {
+ if (this.isRunning() && null != consumer) {
+ consumer.unsubscribe(topic);
+ consumer.shutdown();
+ this.running = false;
+ }
+ }
+
+ @Override
+ public synchronized boolean isRunning() {
+ return running;
+ }
+
+ @Override
+ protected synchronized Object doReceive() {
+ List messageExtList = consumer.poll();
+ if (CollectionUtils.isEmpty(messageExtList) || messageExtList.size() > 1) {
+ return null;
+ }
+ MessageExt messageExt = messageExtList.get(0);
+ MessageQueue messageQueue = null;
+ for (MessageQueue queue : assignedMessageQueue.getAssignedMessageQueues()) {
+ if (queue.getQueueId() == messageExt.getQueueId()) {
+ messageQueue = queue;
+ break;
+ }
+ }
+ Message message = RocketMQMessageConverterSupport
+ .convertMessage2Spring(messageExtList.get(0));
+ return MessageBuilder.fromMessage(message)
+ .setHeader(IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK,
+ new RocketMQAckCallback(this.consumer, assignedMessageQueue,
+ messageQueue, messageExt))
+ .build();
+ }
+
+ @Override
+ public String getComponentType() {
+ return "rocketmq:message-source";
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java
new file mode 100644
index 0000000000..7017ba46e2
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2013-2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://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 com.alibaba.cloud.stream.binder.rocketmq.integration.outbound;
+
+import java.lang.reflect.Field;
+
+import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache;
+import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties;
+import com.alibaba.cloud.stream.binder.rocketmq.utils.RocketMQUtils;
+import org.apache.rocketmq.acl.common.AclClientRPCHook;
+import org.apache.rocketmq.acl.common.SessionCredentials;
+import org.apache.rocketmq.client.hook.CheckForbiddenHook;
+import org.apache.rocketmq.client.hook.SendMessageHook;
+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.TraceDispatcher;
+import org.apache.rocketmq.client.trace.hook.SendMessageTraceHookImpl;
+import org.apache.rocketmq.common.UtilAll;
+import org.apache.rocketmq.remoting.RPCHook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
+/**
+ * Extended function related to producer . eg:initial
+ *
+ * @author zkzlx
+ */
+public final class RocketMQProduceFactory {
+
+ private final static Logger log = LoggerFactory
+ .getLogger(RocketMQProduceFactory.class);
+
+ /**
+ * init for the producer,including convert producer params.
+ * @return
+ */
+ public static DefaultMQProducer initRocketMQProducer(String topic,
+ RocketMQProducerProperties producerProperties) {
+ Assert.notNull(producerProperties.getGroup(),
+ "Property 'group' is required - producerGroup");
+ Assert.notNull(producerProperties.getNameServer(),
+ "Property 'nameServer' is required");
+
+ RPCHook rpcHook = null;
+ if (!StringUtils.isEmpty(producerProperties.getAccessKey())
+ && !StringUtils.isEmpty(producerProperties.getSecretKey())) {
+ rpcHook = new AclClientRPCHook(
+ new SessionCredentials(producerProperties.getAccessKey(),
+ producerProperties.getSecretKey()));
+ }
+ DefaultMQProducer producer;
+ if (RocketMQProducerProperties.ProducerType.Trans
+ .equalsName(producerProperties.getProducerType())) {
+ producer = new TransactionMQProducer(producerProperties.getNamespace(),
+ producerProperties.getGroup(), rpcHook);
+ if (producerProperties.getEnableMsgTrace()) {
+ try {
+ AsyncTraceDispatcher dispatcher = new AsyncTraceDispatcher(
+ producerProperties.getGroup(), TraceDispatcher.Type.PRODUCE,
+ producerProperties.getCustomizedTraceTopic(), rpcHook);
+ 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 mq-trace hook init failed ,maybe can't send msg trace data");
+ }
+ }
+ }
+ else {
+ producer = new DefaultMQProducer(producerProperties.getNamespace(),
+ producerProperties.getGroup(), rpcHook,
+ producerProperties.getEnableMsgTrace(),
+ producerProperties.getCustomizedTraceTopic());
+ }
+
+ producer.setVipChannelEnabled(
+ null == rpcHook && producerProperties.getVipChannelEnabled());
+ producer.setInstanceName(
+ RocketMQUtils.getInstanceName(rpcHook, topic + "|" + UtilAll.getPid()));
+ producer.setNamesrvAddr(producerProperties.getNameServer());
+ producer.setSendMsgTimeout(producerProperties.getSendMsgTimeout());
+ producer.setRetryTimesWhenSendFailed(
+ producerProperties.getRetryTimesWhenSendFailed());
+ producer.setRetryTimesWhenSendAsyncFailed(
+ producerProperties.getRetryTimesWhenSendAsyncFailed());
+ producer.setCompressMsgBodyOverHowmuch(
+ producerProperties.getCompressMsgBodyThreshold());
+ producer.setRetryAnotherBrokerWhenNotStoreOK(
+ producerProperties.getRetryAnotherBroker());
+ producer.setMaxMessageSize(producerProperties.getMaxMessageSize());
+ producer.setUseTLS(producerProperties.getUseTLS());
+ CheckForbiddenHook checkForbiddenHook = RocketMQBeanContainerCache.getBean(
+ producerProperties.getCheckForbiddenHook(), CheckForbiddenHook.class);
+ if (null != checkForbiddenHook) {
+ producer.getDefaultMQProducerImpl()
+ .registerCheckForbiddenHook(checkForbiddenHook);
+ }
+ SendMessageHook sendMessageHook = RocketMQBeanContainerCache
+ .getBean(producerProperties.getSendMessageHook(), SendMessageHook.class);
+ if (null != sendMessageHook) {
+ producer.getDefaultMQProducerImpl().registerSendMessageHook(sendMessageHook);
+ }
+
+ return producer;
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java
new file mode 100644
index 0000000000..66b58f7973
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.integration.outbound;
+
+import java.util.List;
+
+import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst;
+import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache;
+import com.alibaba.cloud.stream.binder.rocketmq.metrics.Instrumentation;
+import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager;
+import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties;
+import com.alibaba.cloud.stream.binder.rocketmq.provisioning.selector.PartitionMessageQueueSelector;
+import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQMessageConverterSupport;
+import org.apache.rocketmq.client.exception.MQBrokerException;
+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.SendStatus;
+import org.apache.rocketmq.client.producer.TransactionListener;
+import org.apache.rocketmq.client.producer.TransactionMQProducer;
+import org.apache.rocketmq.common.message.MessageQueue;
+import org.apache.rocketmq.remoting.exception.RemotingException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.springframework.cloud.stream.binder.ExtendedProducerProperties;
+import org.springframework.cloud.stream.binding.MessageConverterConfigurer;
+import org.springframework.cloud.stream.binding.MessageConverterConfigurer.PartitioningInterceptor;
+import org.springframework.cloud.stream.provisioning.ProducerDestination;
+import org.springframework.context.Lifecycle;
+import org.springframework.integration.handler.AbstractMessageHandler;
+import org.springframework.integration.support.ErrorMessageStrategy;
+import org.springframework.integration.support.ErrorMessageUtils;
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.MessagingException;
+
+/**
+ * @author Jim
+ */
+public class RocketMQProducerMessageHandler extends AbstractMessageHandler
+ implements Lifecycle {
+
+ private final static Logger log = LoggerFactory
+ .getLogger(RocketMQProducerMessageHandler.class);
+
+ private volatile boolean running = false;
+ private volatile boolean isTrans = false;
+
+ private ErrorMessageStrategy errorMessageStrategy;
+ private MessageChannel sendFailureChannel;
+ private MessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor;
+ private DefaultMQProducer defaultMQProducer;
+ private MessageQueueSelector messageQueueSelector;
+
+ private final ProducerDestination destination;
+ private final ExtendedProducerProperties extendedProducerProperties;
+ private final RocketMQProducerProperties mqProducerProperties;
+
+ public RocketMQProducerMessageHandler(ProducerDestination destination,
+ ExtendedProducerProperties extendedProducerProperties,
+ RocketMQProducerProperties mqProducerProperties) {
+ this.destination = destination;
+ this.extendedProducerProperties = extendedProducerProperties;
+ this.mqProducerProperties = mqProducerProperties;
+ }
+
+ @Override
+ protected void onInit() {
+ if (null == mqProducerProperties || !mqProducerProperties.getEnabled()) {
+ return;
+ }
+ super.onInit();
+ this.defaultMQProducer = RocketMQProduceFactory
+ .initRocketMQProducer(destination.getName(), mqProducerProperties);
+ this.isTrans = defaultMQProducer instanceof TransactionMQProducer;
+ // Use the default if the partition is on and no customization is available.
+ this.messageQueueSelector = RocketMQBeanContainerCache.getBean(
+ mqProducerProperties.getMessageQueueSelector(),
+ MessageQueueSelector.class,
+ extendedProducerProperties.isPartitioned()
+ ? new PartitionMessageQueueSelector()
+ : null);
+ }
+
+ @Override
+ public void start() {
+ Instrumentation instrumentation = new Instrumentation(destination.getName(),
+ this);
+ try {
+ defaultMQProducer.start();
+ // TransactionMQProducer does not currently support custom
+ // MessageQueueSelector.
+ if (!isTrans && extendedProducerProperties.isPartitioned()) {
+ List messageQueues = defaultMQProducer
+ .fetchPublishMessageQueues(destination.getName());
+ if (extendedProducerProperties.getPartitionCount() != messageQueues
+ .size()) {
+ logger.info(String.format(
+ "The partition count of topic '%s' will change from '%s' to '%s'",
+ destination.getName(),
+ extendedProducerProperties.getPartitionCount(),
+ messageQueues.size()));
+ extendedProducerProperties.setPartitionCount(messageQueues.size());
+ // may be npe!
+ partitioningInterceptor.setPartitionCount(
+ extendedProducerProperties.getPartitionCount());
+ }
+ }
+ running = true;
+ instrumentation.markStartedSuccessfully();
+ }
+ catch (MQClientException | NullPointerException e) {
+ instrumentation.markStartFailed(e);
+ log.error("The defaultMQProducer startup failure !!!", e);
+ }
+ finally {
+ InstrumentationManager.addHealthInstrumentation(instrumentation);
+ }
+ }
+
+ @Override
+ public void stop() {
+ if (running && null != defaultMQProducer) {
+ defaultMQProducer.shutdown();
+ }
+ running = false;
+ }
+
+ @Override
+ public boolean isRunning() {
+ return running;
+ }
+
+ @Override
+ protected void handleMessageInternal(Message> message) {
+ try {
+ org.apache.rocketmq.common.message.Message mqMessage = RocketMQMessageConverterSupport
+ .convertMessage2MQ(destination.getName(), message);
+ SendResult sendResult;
+ if (defaultMQProducer instanceof TransactionMQProducer) {
+ TransactionListener transactionListener = RocketMQBeanContainerCache
+ .getBean(mqProducerProperties.getTransactionListener(),
+ TransactionListener.class);
+ if (transactionListener == null) {
+ throw new MessagingException(
+ "TransactionMQProducer must have a TransactionMQProducer !!! ");
+ }
+ ((TransactionMQProducer) defaultMQProducer)
+ .setTransactionListener(transactionListener);
+ log.info("send transaction message :" + mqMessage);
+ sendResult = defaultMQProducer.sendMessageInTransaction(mqMessage,
+ message.getHeaders().get(RocketMQConst.USER_TRANSACTIONAL_ARGS));
+ }
+ else {
+ log.info("send message :" + mqMessage);
+ sendResult = this.send(mqMessage, this.messageQueueSelector,
+ message.getHeaders(), message);
+ }
+ if (sendResult == null
+ || !SendStatus.SEND_OK.equals(sendResult.getSendStatus())) {
+ log.error("message send fail.SendStatus is not OK ");
+ this.doFail(message, new MessagingException(
+ "message send fail.SendStatus is not OK."));
+ }
+ }
+ catch (Exception e) {
+ log.error("RocketMQ Message hasn't been sent. Caused by " + e.getMessage(),
+ e);
+ this.doFail(message, e);
+ }
+ }
+
+ private SendResult send(org.apache.rocketmq.common.message.Message mqMessage,
+ MessageQueueSelector selector, Object args, Message> message)
+ throws RemotingException, MQClientException, InterruptedException,
+ MQBrokerException {
+ SendResult sendResult = new SendResult();
+ sendResult.setSendStatus(SendStatus.SEND_OK);
+ if (RocketMQProducerProperties.SendType.OneWay
+ .equalsName(mqProducerProperties.getSendType())) {
+ if (null != selector) {
+ defaultMQProducer.sendOneway(mqMessage, selector, args);
+ }
+ else {
+ defaultMQProducer.sendOneway(mqMessage);
+ }
+ return sendResult;
+ }
+ if (RocketMQProducerProperties.SendType.Sync
+ .equalsName(mqProducerProperties.getSendType())) {
+ if (null != selector) {
+ return defaultMQProducer.send(mqMessage, selector, args);
+ }
+ return defaultMQProducer.send(mqMessage);
+ }
+ if (RocketMQProducerProperties.SendType.Async
+ .equalsName(mqProducerProperties.getSendType())) {
+ if (null != selector) {
+ defaultMQProducer.send(mqMessage, selector, args,
+ this.getSendCallback(message));
+ }
+ else {
+ defaultMQProducer.send(mqMessage, this.getSendCallback(message));
+ }
+ return sendResult;
+ }
+ throw new MessagingException(
+ "message hasn't been sent,cause by : the SendType must be in this values[OneWay, Async, Sync]");
+ }
+
+ /**
+ * https://github.com/alibaba/spring-cloud-alibaba/issues/1408
+ * @param message
+ * @return
+ */
+ private SendCallback getSendCallback(Message> message) {
+ SendCallback sendCallback = RocketMQBeanContainerCache
+ .getBean(mqProducerProperties.getSendCallBack(), SendCallback.class);
+ if (null == sendCallback) {
+ sendCallback = new SendCallback() {
+ @Override
+ public void onSuccess(SendResult sendResult) {
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ RocketMQProducerMessageHandler.this.doFail(message, e);
+ }
+ };
+ }
+ return sendCallback;
+ }
+
+ private void doFail(Message> message, Throwable e) {
+ if (getSendFailureChannel() != null) {
+ getSendFailureChannel().send(getErrorMessageStrategy().buildErrorMessage(e,
+ ErrorMessageUtils.getAttributeAccessor(message, message)));
+ }
+ else {
+ throw new MessagingException(message, e);
+ }
+ }
+
+ public MessageChannel getSendFailureChannel() {
+ return sendFailureChannel;
+ }
+
+ public void setSendFailureChannel(MessageChannel sendFailureChannel) {
+ this.sendFailureChannel = sendFailureChannel;
+ }
+
+ public ErrorMessageStrategy getErrorMessageStrategy() {
+ return errorMessageStrategy;
+ }
+
+ public void setErrorMessageStrategy(ErrorMessageStrategy errorMessageStrategy) {
+ this.errorMessageStrategy = errorMessageStrategy;
+ }
+
+ public PartitioningInterceptor getPartitioningInterceptor() {
+ return partitioningInterceptor;
+ }
+
+ public RocketMQProducerMessageHandler setPartitioningInterceptor(
+ PartitioningInterceptor partitioningInterceptor) {
+ this.partitioningInterceptor = partitioningInterceptor;
+ return this;
+ }
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java
new file mode 100644
index 0000000000..00e7d30dd7
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.properties;
+
+import java.io.Serializable;
+
+import org.apache.rocketmq.client.AccessChannel;
+import org.apache.rocketmq.client.impl.factory.MQClientInstance;
+import org.apache.rocketmq.remoting.netty.TlsSystemConfig;
+
+/**
+ * @author zkzlx
+ */
+public class RocketMQCommonProperties implements Serializable {
+ private static final long serialVersionUID = -6724870154343284715L;
+
+ private boolean enabled = true;
+
+ private String nameServer;
+
+ /**
+ * The property of "access-key".
+ */
+ private String accessKey;
+
+ /**
+ * The property of "secret-key".
+ */
+ private String secretKey;
+ /**
+ * Consumers of the same role is required to have exactly same subscriptions and
+ * consumerGroup to correctly achieve load balance. It's required and needs to be
+ * globally unique.
+ *
+ * Producer group conceptually aggregates all producer instances of exactly same role,
+ * which is particularly important when transactional messages are involved.
+ *
+ *
+ * For non-transactional messages, it does not matter as long as it's unique per
+ * process.
+ *
+ *
+ * See here for further
+ * discussion.
+ */
+ private String group;
+
+ private String namespace;
+ private String accessChannel = AccessChannel.LOCAL.name();
+ /**
+ * Pulling topic information interval from the named server.
+ * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask
+ * updateTopicRouteInfoFromNameServer.
+ */
+ private int pollNameServerInterval = 1000 * 30;
+ /**
+ * Heartbeat interval in microseconds with message broker.
+ * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask
+ * sendHeartbeatToAllBroker .
+ */
+ private int heartbeatBrokerInterval = 1000 * 30;
+ /**
+ * Offset persistent interval for consumer.
+ * see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask
+ * sendHeartbeatToAllBroker .
+ */
+ private int persistConsumerOffsetInterval = 1000 * 5;
+
+ private boolean vipChannelEnabled = false;
+
+ private boolean useTLS = TlsSystemConfig.tlsEnable;
+
+ private boolean enableMsgTrace = true;
+ private String customizedTraceTopic;
+
+ public boolean getEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String getNameServer() {
+ return nameServer;
+ }
+
+ public void setNameServer(String nameServer) {
+ this.nameServer = nameServer;
+ }
+
+ 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 String getGroup() {
+ return group;
+ }
+
+ public void setGroup(String group) {
+ this.group = group;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public String getAccessChannel() {
+ return accessChannel;
+ }
+
+ public void setAccessChannel(String accessChannel) {
+ this.accessChannel = accessChannel;
+ }
+
+ public int getPollNameServerInterval() {
+ return pollNameServerInterval;
+ }
+
+ public void setPollNameServerInterval(int pollNameServerInterval) {
+ this.pollNameServerInterval = pollNameServerInterval;
+ }
+
+ public int getHeartbeatBrokerInterval() {
+ return heartbeatBrokerInterval;
+ }
+
+ public void setHeartbeatBrokerInterval(int heartbeatBrokerInterval) {
+ this.heartbeatBrokerInterval = heartbeatBrokerInterval;
+ }
+
+ public int getPersistConsumerOffsetInterval() {
+ return persistConsumerOffsetInterval;
+ }
+
+ public void setPersistConsumerOffsetInterval(int persistConsumerOffsetInterval) {
+ this.persistConsumerOffsetInterval = persistConsumerOffsetInterval;
+ }
+
+ public boolean getVipChannelEnabled() {
+ return vipChannelEnabled;
+ }
+
+ public void setVipChannelEnabled(boolean vipChannelEnabled) {
+ this.vipChannelEnabled = vipChannelEnabled;
+ }
+
+ public boolean getUseTLS() {
+ return useTLS;
+ }
+
+ public void setUseTLS(boolean useTLS) {
+ this.useTLS = useTLS;
+ }
+
+ public boolean getEnableMsgTrace() {
+ return enableMsgTrace;
+ }
+
+ public void setEnableMsgTrace(boolean enableMsgTrace) {
+ this.enableMsgTrace = enableMsgTrace;
+ }
+
+ public String getCustomizedTraceTopic() {
+ return customizedTraceTopic;
+ }
+
+ public void setCustomizedTraceTopic(String customizedTraceTopic) {
+ this.customizedTraceTopic = customizedTraceTopic;
+ }
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java
new file mode 100644
index 0000000000..99a1a36fb8
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQSpecificPropertiesProvider.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.properties;
+
+import org.springframework.cloud.stream.binder.BinderSpecificPropertiesProvider;
+
+/**
+ * Container object for RocketMQ specific extended producer and consumer binding
+ * properties.
+ *
+ * @author Jim
+ */
+public class RocketMQSpecificPropertiesProvider
+ implements BinderSpecificPropertiesProvider {
+
+ /**
+ * Consumer specific binding properties. @see {@link RocketMQConsumerProperties}.
+ */
+ private RocketMQConsumerProperties consumer = new RocketMQConsumerProperties();
+
+ /**
+ * Producer specific binding properties. @see {@link RocketMQProducerProperties}.
+ */
+ private RocketMQProducerProperties producer = new RocketMQProducerProperties();
+
+ /**
+ * @return {@link RocketMQConsumerProperties} Consumer specific binding
+ * properties. @see {@link RocketMQConsumerProperties}.
+ */
+ @Override
+ public RocketMQConsumerProperties getConsumer() {
+ return this.consumer;
+ }
+
+ public void setConsumer(RocketMQConsumerProperties consumer) {
+ this.consumer = consumer;
+ }
+
+ /**
+ * @return {@link RocketMQProducerProperties} Producer specific binding
+ * properties. @see {@link RocketMQProducerProperties}.
+ */
+ @Override
+ public RocketMQProducerProperties getProducer() {
+ return this.producer;
+ }
+
+ public void setProducer(RocketMQProducerProperties producer) {
+ this.producer = producer;
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java
new file mode 100644
index 0000000000..d4b62e5fa5
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/support/RocketMQMessageConverterSupport.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.support;
+
+import java.nio.charset.Charset;
+import java.util.Map;
+import java.util.Objects;
+
+import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst;
+import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst.Headers;
+import com.alibaba.cloud.stream.binder.rocketmq.convert.RocketMQMessageConverter;
+import com.alibaba.cloud.stream.binder.rocketmq.custom.RocketMQBeanContainerCache;
+import org.apache.rocketmq.common.message.MessageConst;
+import org.apache.rocketmq.common.message.MessageExt;
+
+import org.springframework.messaging.Message;
+import org.springframework.messaging.MessageHeaders;
+import org.springframework.messaging.converter.CompositeMessageConverter;
+import org.springframework.messaging.support.MessageBuilder;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.util.StringUtils;
+
+/**
+ *
+ * @author zkzlx
+ */
+public class RocketMQMessageConverterSupport {
+
+ private static final CompositeMessageConverter MESSAGE_CONVERTER = RocketMQBeanContainerCache
+ .getBean(RocketMQMessageConverter.DEFAULT_NAME,
+ CompositeMessageConverter.class,
+ new RocketMQMessageConverter().getMessageConverter());
+
+ public static Message convertMessage2Spring(MessageExt message) {
+ MessageBuilder messageBuilder = MessageBuilder.withPayload(message.getBody())
+ .setHeader(toRocketHeaderKey(Headers.KEYS), message.getKeys())
+ .setHeader(toRocketHeaderKey(Headers.TAGS), message.getTags())
+ .setHeader(toRocketHeaderKey(Headers.TOPIC), message.getTopic())
+ .setHeader(toRocketHeaderKey(Headers.MESSAGE_ID), message.getMsgId())
+ .setHeader(toRocketHeaderKey(Headers.BORN_TIMESTAMP),
+ message.getBornTimestamp())
+ .setHeader(toRocketHeaderKey(Headers.BORN_HOST),
+ message.getBornHostString())
+ .setHeader(toRocketHeaderKey(Headers.FLAG), message.getFlag())
+ .setHeader(toRocketHeaderKey(Headers.QUEUE_ID), message.getQueueId())
+ .setHeader(toRocketHeaderKey(Headers.SYS_FLAG), message.getSysFlag())
+ .setHeader(toRocketHeaderKey(Headers.TRANSACTION_ID),
+ message.getTransactionId());
+ addUserProperties(message.getProperties(), messageBuilder);
+ return messageBuilder.build();
+ }
+
+ public static String toRocketHeaderKey(String rawKey) {
+ return "ROCKET_" + rawKey;
+ }
+
+ private static void addUserProperties(Map properties,
+ MessageBuilder messageBuilder) {
+ if (!CollectionUtils.isEmpty(properties)) {
+ properties.forEach((key, val) -> {
+ if (!MessageConst.STRING_HASH_SET.contains(key)
+ && !MessageHeaders.ID.equals(key)
+ && !MessageHeaders.TIMESTAMP.equals(key)) {
+ messageBuilder.setHeader(key, val);
+ }
+ });
+ }
+ }
+
+ public static org.apache.rocketmq.common.message.Message convertMessage2MQ(
+ String destination, Message> source) {
+ Message> message = MESSAGE_CONVERTER.toMessage(source.getPayload(),
+ source.getHeaders());
+ assert message != null;
+ MessageBuilder> builder = MessageBuilder.fromMessage(message);
+ builder.setHeaderIfAbsent(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN);
+ message = builder.build();
+ return doConvert(destination, message);
+ }
+
+ private static org.apache.rocketmq.common.message.Message doConvert(String topic,
+ Message> message) {
+ Charset charset = Charset.defaultCharset();
+ Object payloadObj = message.getPayload();
+ byte[] payloads;
+ try {
+ if (payloadObj instanceof String) {
+ payloads = ((String) payloadObj).getBytes(charset);
+ }
+ else if (payloadObj instanceof byte[]) {
+ payloads = (byte[]) message.getPayload();
+ }
+ else {
+ String jsonObj = (String) MESSAGE_CONVERTER.fromMessage(message,
+ payloadObj.getClass());
+ if (null == jsonObj) {
+ throw new RuntimeException(String.format(
+ "empty after conversion [messageConverter:%s,payloadClass:%s,payloadObj:%s]",
+ MESSAGE_CONVERTER.getClass(), payloadObj.getClass(),
+ payloadObj));
+ }
+ payloads = jsonObj.getBytes(charset);
+ }
+ }
+ catch (Exception e) {
+ throw new RuntimeException("convert to RocketMQ message failed.", e);
+ }
+ return getAndWrapMessage(topic, message.getHeaders(), payloads);
+ }
+
+ private static org.apache.rocketmq.common.message.Message getAndWrapMessage(
+ String topic, MessageHeaders headers, byte[] payloads) {
+ if (topic == null || topic.length() < 1) {
+ return null;
+ }
+ if (payloads == null || payloads.length < 1) {
+ return null;
+ }
+ org.apache.rocketmq.common.message.Message rocketMsg = new org.apache.rocketmq.common.message.Message(
+ topic, payloads);
+ if (Objects.nonNull(headers) && !headers.isEmpty()) {
+ Object tag = headers.getOrDefault(Headers.TAGS,
+ headers.get(toRocketHeaderKey(Headers.TAGS)));
+ if (!StringUtils.isEmpty(tag)) {
+ rocketMsg.setTags(String.valueOf(tag));
+ }
+
+ Object keys = headers.getOrDefault(Headers.KEYS,
+ headers.get(toRocketHeaderKey(Headers.KEYS)));
+ if (!StringUtils.isEmpty(keys)) {
+ rocketMsg.setKeys(keys.toString());
+ }
+ Object flagObj = headers.getOrDefault(Headers.FLAG,
+ headers.get(toRocketHeaderKey(Headers.FLAG)));
+ int flag = 0;
+ int delayLevel = 0;
+ try {
+ flagObj = flagObj == null ? 0 : flagObj;
+ Object delayLevelObj = headers.getOrDefault(
+ RocketMQConst.PROPERTY_DELAY_TIME_LEVEL,
+ headers.get(toRocketHeaderKey(
+ RocketMQConst.PROPERTY_DELAY_TIME_LEVEL)));
+ delayLevelObj = delayLevelObj == null ? 0 : delayLevelObj;
+ delayLevel = Integer.parseInt(String.valueOf(delayLevelObj));
+ flag = Integer.parseInt(String.valueOf(flagObj));
+ }
+ catch (Exception ignored) {
+ }
+ if (delayLevel > 0) {
+ rocketMsg.setDelayTimeLevel(delayLevel);
+ }
+ rocketMsg.setFlag(flag);
+ Object waitStoreMsgOkObj = headers
+ .getOrDefault(RocketMQConst.PROPERTY_WAIT_STORE_MSG_OK, "true");
+ rocketMsg.setWaitStoreMsgOK(
+ Boolean.parseBoolean(String.valueOf(waitStoreMsgOkObj)));
+ headers.entrySet().stream()
+ .filter(entry -> !Objects.equals(entry.getKey(), Headers.FLAG))
+ .forEach(entry -> {
+ if (!MessageConst.STRING_HASH_SET.contains(entry.getKey())) {
+ rocketMsg.putUserProperty(entry.getKey(),
+ String.valueOf(entry.getValue()));
+ }
+ });
+
+ }
+ return rocketMsg;
+ }
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java
new file mode 100644
index 0000000000..3f7898422b
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.alibaba.cloud.stream.binder.rocketmq.utils;
+
+import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;
+import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQCommonProperties;
+import org.apache.rocketmq.acl.common.AclClientRPCHook;
+import org.apache.rocketmq.acl.common.SessionCredentials;
+import org.apache.rocketmq.client.consumer.MessageSelector;
+import org.apache.rocketmq.common.UtilAll;
+import org.apache.rocketmq.remoting.RPCHook;
+
+import org.springframework.util.StringUtils;
+
+/**
+ * TODO Describe what it does
+ *
+ * @author Jim
+ */
+public class RocketMQUtils {
+
+ public static T mergeRocketMQProperties(
+ RocketMQBinderConfigurationProperties binderConfigurationProperties,
+ T mqProperties) {
+ if (null == binderConfigurationProperties || mqProperties == null) {
+ return mqProperties;
+ }
+ if (StringUtils.isEmpty(mqProperties.getNameServer())) {
+ mqProperties.setNameServer(binderConfigurationProperties.getNameServer());
+ }
+ if (StringUtils.isEmpty(mqProperties.getSecretKey())) {
+ mqProperties.setSecretKey(binderConfigurationProperties.getSecretKey());
+ }
+ if (StringUtils.isEmpty(mqProperties.getAccessKey())) {
+ mqProperties.setAccessKey(binderConfigurationProperties.getAccessKey());
+ }
+ if (StringUtils.isEmpty(mqProperties.getAccessChannel())) {
+ mqProperties
+ .setAccessChannel(binderConfigurationProperties.getAccessChannel());
+ }
+ if (StringUtils.isEmpty(mqProperties.getNamespace())) {
+ mqProperties.setNamespace(binderConfigurationProperties.getNamespace());
+ }
+ if (StringUtils.isEmpty(mqProperties.getGroup())) {
+ mqProperties.setGroup(binderConfigurationProperties.getGroup());
+ }
+ if (StringUtils.isEmpty(mqProperties.getCustomizedTraceTopic())) {
+ mqProperties.setCustomizedTraceTopic(
+ binderConfigurationProperties.getCustomizedTraceTopic());
+ }
+ mqProperties.setNameServer(getNameServerStr(mqProperties.getNameServer()));
+ return mqProperties;
+ }
+
+ public static String getInstanceName(RPCHook rpcHook, String identify) {
+ String separator = "|";
+ StringBuilder instanceName = new StringBuilder();
+ if (null != rpcHook) {
+ SessionCredentials sessionCredentials = ((AclClientRPCHook) rpcHook)
+ .getSessionCredentials();
+ instanceName.append(sessionCredentials.getAccessKey()).append(separator)
+ .append(sessionCredentials.getSecretKey()).append(separator);
+ }
+ instanceName.append(identify).append(separator).append(UtilAll.getPid());
+ return instanceName.toString();
+ }
+
+ public static String getNameServerStr(String nameServer) {
+ if (StringUtils.isEmpty(nameServer)) {
+ return null;
+ }
+ return nameServer.replaceAll(",", ";");
+ }
+
+ private static final String SQL = "sql:";
+
+ public static MessageSelector getMessageSelector(String expression) {
+ if (StringUtils.hasText(expression) && expression.startsWith(SQL)) {
+ return MessageSelector.bySql(expression.replaceFirst(SQL, ""));
+ }
+ return MessageSelector.byTag(expression);
+ }
+
+}
From 5a763e0ec987041ae85702bfe36494bbc45f1ecf Mon Sep 17 00:00:00 2001
From: zkzlx
Date: Mon, 1 Feb 2021 11:29:37 +0800
Subject: [PATCH 03/19] Code refactoring and some new feature support - delete
some invalid files.
---
.../rocketmq/RocketMQBinderConstants.java | 51 ---------
.../RocketMQBinderAutoConfiguration.java | 81 --------------
...inderHealthIndicatorAutoConfiguration.java | 40 -------
...etMQComponent4BinderAutoConfiguration.java | 102 ------------------
.../main/resources/META-INF/spring.binders | 2 +-
.../main/resources/META-INF/spring.factories | 2 +-
6 files changed, 2 insertions(+), 276 deletions(-)
delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderConstants.java
delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderAutoConfiguration.java
delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderHealthIndicatorAutoConfiguration.java
delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderConstants.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderConstants.java
deleted file mode 100644
index 47e4b9e7f8..0000000000
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQBinderConstants.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2013-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://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 com.alibaba.cloud.stream.binder.rocketmq;
-
-import static org.apache.rocketmq.spring.support.RocketMQHeaders.PREFIX;
-
-/**
- * @author Jim
- * @author Xiejiashuai
- */
-public final class RocketMQBinderConstants {
-
- /**
- * Header key for RocketMQ Transactional Args.
- */
- public static final String ROCKET_TRANSACTIONAL_ARG = "TRANSACTIONAL_ARG";
-
- /**
- * Default NameServer value.
- */
- public static final String DEFAULT_NAME_SERVER = "127.0.0.1:9876";
-
- /**
- * Default group for SCS RocketMQ Binder.
- */
- public static final String DEFAULT_GROUP = PREFIX + "binder_default_group_name";
-
- /**
- * RocketMQ re-consume times.
- */
- public static final String ROCKETMQ_RECONSUME_TIMES = PREFIX + "RECONSUME_TIMES";
-
- private RocketMQBinderConstants() {
- throw new AssertionError("Must not instantiate constant utility class");
- }
-
-}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderAutoConfiguration.java
deleted file mode 100644
index 3031c26564..0000000000
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderAutoConfiguration.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2013-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://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 com.alibaba.cloud.stream.binder.rocketmq.config;
-
-import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder;
-import com.alibaba.cloud.stream.binder.rocketmq.metrics.InstrumentationManager;
-import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;
-import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties;
-import com.alibaba.cloud.stream.binder.rocketmq.provisioning.RocketMQTopicProvisioner;
-import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration;
-import org.apache.rocketmq.spring.autoconfigure.RocketMQProperties;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-
-/**
- * @author Timur Valiev
- * @author Jim
- */
-@Configuration(proxyBeanMethods = false)
-@Import({ RocketMQAutoConfiguration.class,
- RocketMQBinderHealthIndicatorAutoConfiguration.class })
-@EnableConfigurationProperties({ RocketMQBinderConfigurationProperties.class,
- RocketMQExtendedBindingProperties.class })
-public class RocketMQBinderAutoConfiguration {
-
- private final RocketMQExtendedBindingProperties extendedBindingProperties;
-
- private final RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties;
-
- @Autowired(required = false)
- private RocketMQProperties rocketMQProperties = new RocketMQProperties();
-
- @Autowired
- public RocketMQBinderAutoConfiguration(
- RocketMQExtendedBindingProperties extendedBindingProperties,
- RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties) {
- this.extendedBindingProperties = extendedBindingProperties;
- this.rocketBinderConfigurationProperties = rocketBinderConfigurationProperties;
- }
-
- @Bean
- public RocketMQTopicProvisioner provisioningProvider() {
- return new RocketMQTopicProvisioner();
- }
-
- @Bean
- public RocketMQMessageChannelBinder rocketMessageChannelBinder(
- RocketMQTopicProvisioner provisioningProvider,
- InstrumentationManager instrumentationManager) {
- RocketMQMessageChannelBinder binder = new RocketMQMessageChannelBinder(
- provisioningProvider, extendedBindingProperties,
- rocketBinderConfigurationProperties, rocketMQProperties,
- instrumentationManager);
- binder.setExtendedBindingProperties(extendedBindingProperties);
- return binder;
- }
-
- @Bean
- public InstrumentationManager instrumentationManager() {
- return new InstrumentationManager();
- }
-
-}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderHealthIndicatorAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderHealthIndicatorAutoConfiguration.java
deleted file mode 100644
index 1c3b5dc0d1..0000000000
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQBinderHealthIndicatorAutoConfiguration.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2013-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://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 com.alibaba.cloud.stream.binder.rocketmq.config;
-
-import com.alibaba.cloud.stream.binder.rocketmq.actuator.RocketMQBinderHealthIndicator;
-
-import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
-import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * @author Jim
- */
-@Configuration(proxyBeanMethods = false)
-@ConditionalOnClass(Endpoint.class)
-public class RocketMQBinderHealthIndicatorAutoConfiguration {
-
- @Bean
- @ConditionalOnEnabledHealthIndicator("rocketmq")
- public RocketMQBinderHealthIndicator rocketBinderHealthIndicator() {
- return new RocketMQBinderHealthIndicator();
- }
-
-}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java
deleted file mode 100644
index 6968ead86a..0000000000
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/config/RocketMQComponent4BinderAutoConfiguration.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2013-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://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 com.alibaba.cloud.stream.binder.rocketmq.config;
-
-import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.rocketmq.acl.common.AclClientRPCHook;
-import org.apache.rocketmq.acl.common.SessionCredentials;
-import org.apache.rocketmq.client.producer.DefaultMQProducer;
-import org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration;
-import org.apache.rocketmq.spring.config.RocketMQConfigUtils;
-import org.apache.rocketmq.spring.config.RocketMQTransactionAnnotationProcessor;
-import org.apache.rocketmq.spring.config.TransactionHandlerRegistry;
-import org.apache.rocketmq.spring.core.RocketMQTemplate;
-
-import org.springframework.boot.autoconfigure.AutoConfigureAfter;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.env.Environment;
-import org.springframework.util.StringUtils;
-
-/**
- * @author Jim
- */
-@Configuration(proxyBeanMethods = false)
-@AutoConfigureAfter(RocketMQAutoConfiguration.class)
-@ConditionalOnMissingBean(DefaultMQProducer.class)
-public class RocketMQComponent4BinderAutoConfiguration {
-
- private final Environment environment;
-
- public RocketMQComponent4BinderAutoConfiguration(Environment environment) {
- this.environment = environment;
- }
-
- @Bean
- @ConditionalOnMissingBean(DefaultMQProducer.class)
- public DefaultMQProducer defaultMQProducer() {
- DefaultMQProducer producer;
- String configNameServer = environment.resolveRequiredPlaceholders(
- "${spring.cloud.stream.rocketmq.binder.name-server:${rocketmq.producer.name-server:}}");
- String ak = environment.resolveRequiredPlaceholders(
- "${spring.cloud.stream.rocketmq.binder.access-key:${rocketmq.producer.access-key:}}");
- String sk = environment.resolveRequiredPlaceholders(
- "${spring.cloud.stream.rocketmq.binder.secret-key:${rocketmq.producer.secret-key:}}");
- if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) {
- producer = new DefaultMQProducer(RocketMQBinderConstants.DEFAULT_GROUP,
- new AclClientRPCHook(new SessionCredentials(ak, sk)));
- producer.setVipChannelEnabled(false);
- }
- else {
- producer = new DefaultMQProducer(RocketMQBinderConstants.DEFAULT_GROUP);
- }
- if (StringUtils.isEmpty(configNameServer)) {
- configNameServer = RocketMQBinderConstants.DEFAULT_NAME_SERVER;
- }
- producer.setNamesrvAddr(configNameServer);
- return producer;
- }
-
- @Bean(destroyMethod = "destroy")
- @ConditionalOnMissingBean
- public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer,
- ObjectMapper objectMapper) {
- RocketMQTemplate rocketMQTemplate = new RocketMQTemplate();
- rocketMQTemplate.setProducer(mqProducer);
- rocketMQTemplate.setObjectMapper(objectMapper);
- return rocketMQTemplate;
- }
-
- @Bean
- @ConditionalOnBean(RocketMQTemplate.class)
- @ConditionalOnMissingBean(TransactionHandlerRegistry.class)
- public TransactionHandlerRegistry transactionHandlerRegistry(
- RocketMQTemplate template) {
- return new TransactionHandlerRegistry(template);
- }
-
- @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME)
- @ConditionalOnBean(TransactionHandlerRegistry.class)
- public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor(
- TransactionHandlerRegistry transactionHandlerRegistry) {
- return new RocketMQTransactionAnnotationProcessor(transactionHandlerRegistry);
- }
-
-}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.binders b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.binders
index 2e5b995386..b232e1f10f 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.binders
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.binders
@@ -1 +1 @@
-rocketmq:com.alibaba.cloud.stream.binder.rocketmq.config.RocketMQBinderAutoConfiguration
\ No newline at end of file
+rocketmq:com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.RocketMQBinderAutoConfiguration
\ No newline at end of file
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories
index 82d344e00b..e18651dc41 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/resources/META-INF/spring.factories
@@ -1,2 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-com.alibaba.cloud.stream.binder.rocketmq.config.RocketMQComponent4BinderAutoConfiguration
+com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.ExtendedBindingHandlerMappingsProviderConfiguration
From c1c559717154a92d87739450ea85e3186fea4029 Mon Sep 17 00:00:00 2001
From: zkzlx
Date: Mon, 1 Feb 2021 13:46:28 +0800
Subject: [PATCH 04/19] Code refactoring and some new feature support - delete
some invalid files.
---
.../RocketMQListenerBindingContainer.java | 470 ------------------
.../RocketMQMessageQueueChooser.java | 62 ---
2 files changed, 532 deletions(-)
delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java
delete mode 100644 spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQMessageQueueChooser.java
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java
deleted file mode 100644
index 7bd875f33b..0000000000
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQListenerBindingContainer.java
+++ /dev/null
@@ -1,470 +0,0 @@
-/// *
-// * Copyright 2013-2018 the original author or authors.
-// *
-// * Licensed under the Apache License, Version 2.0 (the "License");
-// * you may not use this file except in compliance with the License.
-// * You may obtain a copy of the License at
-// *
-// * https://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 com.alibaba.cloud.stream.binder.rocketmq.consuming;
-//
-// import java.util.List;
-// import java.util.Objects;
-//
-// import com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderUtils;
-// import com.alibaba.cloud.stream.binder.rocketmq.RocketMQMessageChannelBinder;
-// import
-/// com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;
-// import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQConsumerProperties;
-// import com.alibaba.cloud.stream.binder.rocketmq.support.RocketMQHeaderMapper;
-// import org.apache.rocketmq.acl.common.AclClientRPCHook;
-// import org.apache.rocketmq.acl.common.SessionCredentials;
-// 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.rebalance.AllocateMessageQueueAveragely;
-// import org.apache.rocketmq.client.exception.MQClientException;
-// import org.apache.rocketmq.common.UtilAll;
-// import org.apache.rocketmq.common.message.MessageExt;
-// import org.apache.rocketmq.remoting.RPCHook;
-// import org.apache.rocketmq.spring.annotation.ConsumeMode;
-// import org.apache.rocketmq.spring.annotation.MessageModel;
-// 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.support.RocketMQListenerContainer;
-// import org.apache.rocketmq.spring.support.RocketMQUtil;
-// import org.slf4j.Logger;
-// import org.slf4j.LoggerFactory;
-//
-// import org.springframework.beans.factory.InitializingBean;
-// import org.springframework.cloud.stream.binder.ExtendedConsumerProperties;
-// import org.springframework.context.SmartLifecycle;
-// import org.springframework.integration.support.MessageBuilder;
-// import org.springframework.messaging.Message;
-// import org.springframework.util.Assert;
-// import org.springframework.util.StringUtils;
-//
-// import static
-/// com.alibaba.cloud.stream.binder.rocketmq.RocketMQBinderConstants.ROCKETMQ_RECONSUME_TIMES;
-//
-/// **
-// * A class that Listen on rocketmq message.
-// *
-// * this class will delegate {@link RocketMQListener} to handle message
-// *
-// * @author Jim
-// * @author Xiejiashuai
-// * @see RocketMQListener
-// */
-// public class RocketMQListenerBindingContainer
-// implements InitializingBean, RocketMQListenerContainer, SmartLifecycle {
-//
-// private final static Logger log = LoggerFactory
-// .getLogger(RocketMQListenerBindingContainer.class);
-//
-// private long suspendCurrentQueueTimeMillis = 1000;
-//
-// /**
-// * Message consume retry strategy
-// * -1,no retry,put into DLQ directly
-// * 0,broker control retry frequency
-// * >0,client control retry frequency.
-// */
-// private int delayLevelWhenNextConsume = 0;
-//
-// private List nameServer;
-//
-// private String consumerGroup;
-//
-// private String topic;
-//
-// private int consumeThreadMax = 64;
-//
-// private String charset = "UTF-8";
-//
-// private RocketMQListener rocketMQListener;
-//
-// private RocketMQHeaderMapper headerMapper;
-//
-// private DefaultMQPushConsumer consumer;
-//
-// private boolean running;
-//
-// private final ExtendedConsumerProperties
-/// rocketMQConsumerProperties;
-//
-// private final RocketMQMessageChannelBinder rocketMQMessageChannelBinder;
-//
-// private final RocketMQBinderConfigurationProperties
-/// rocketBinderConfigurationProperties;
-//
-// // The following properties came from RocketMQConsumerProperties.
-// private ConsumeMode consumeMode;
-//
-// private SelectorType selectorType;
-//
-// private String selectorExpression;
-//
-// private MessageModel messageModel;
-//
-// public RocketMQListenerBindingContainer(
-// ExtendedConsumerProperties rocketMQConsumerProperties,
-// RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties,
-// RocketMQMessageChannelBinder rocketMQMessageChannelBinder) {
-// this.rocketMQConsumerProperties = rocketMQConsumerProperties;
-// this.rocketBinderConfigurationProperties = rocketBinderConfigurationProperties;
-// this.rocketMQMessageChannelBinder = rocketMQMessageChannelBinder;
-// this.consumeMode = rocketMQConsumerProperties.getExtension().getOrderly()
-// ? ConsumeMode.ORDERLY : ConsumeMode.CONCURRENTLY;
-// if (StringUtils.isEmpty(rocketMQConsumerProperties.getExtension().getSql())) {
-// this.selectorType = SelectorType.TAG;
-// this.selectorExpression = rocketMQConsumerProperties.getExtension().getTags();
-// }
-// else {
-// this.selectorType = SelectorType.SQL92;
-// this.selectorExpression = rocketMQConsumerProperties.getExtension().getSql();
-// }
-// this.messageModel = rocketMQConsumerProperties.getExtension().getBroadcasting()
-// ? MessageModel.BROADCASTING : MessageModel.CLUSTERING;
-// }
-//
-// @Override
-// public void setupMessageListener(RocketMQListener> rocketMQListener) {
-// this.rocketMQListener = rocketMQListener;
-// }
-//
-// @Override
-// public void destroy() throws Exception {
-// this.setRunning(false);
-// if (Objects.nonNull(consumer)) {
-// consumer.shutdown();
-// }
-// log.info("container destroyed, {}", this.toString());
-// }
-//
-// @Override
-// public void afterPropertiesSet() throws Exception {
-// initRocketMQPushConsumer();
-// }
-//
-// @Override
-// public boolean isAutoStartup() {
-// return true;
-// }
-//
-// @Override
-// public void stop(Runnable callback) {
-// stop();
-// callback.run();
-// }
-//
-// @Override
-// public void start() {
-// if (this.isRunning()) {
-// throw new IllegalStateException(
-// "container already running. " + this.toString());
-// }
-//
-// try {
-// consumer.start();
-// }
-// catch (MQClientException e) {
-// throw new IllegalStateException("Failed to start RocketMQ push consumer", e);
-// }
-// this.setRunning(true);
-//
-// log.info("running container: {}", this.toString());
-// }
-//
-// @Override
-// public void stop() {
-// if (this.isRunning()) {
-// if (Objects.nonNull(consumer)) {
-// consumer.shutdown();
-// }
-// setRunning(false);
-// }
-// }
-//
-// @Override
-// public boolean isRunning() {
-// return running;
-// }
-//
-// private void setRunning(boolean running) {
-// this.running = running;
-// }
-//
-// @Override
-// public int getPhase() {
-// return Integer.MAX_VALUE;
-// }
-//
-// private void initRocketMQPushConsumer() throws MQClientException {
-// Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required");
-// Assert.notNull(consumerGroup, "Property 'consumerGroup' is required");
-// Assert.notNull(nameServer, "Property 'nameServer' is required");
-// Assert.notNull(topic, "Property 'topic' is required");
-//
-// String ak = rocketBinderConfigurationProperties.getAccessKey();
-// String sk = rocketBinderConfigurationProperties.getSecretKey();
-// if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) {
-// RPCHook rpcHook = new AclClientRPCHook(new SessionCredentials(ak, sk));
-// consumer = new DefaultMQPushConsumer(consumerGroup, rpcHook,
-// new AllocateMessageQueueAveragely(),
-// rocketBinderConfigurationProperties.isEnableMsgTrace(),
-// rocketBinderConfigurationProperties.getCustomizedTraceTopic());
-// consumer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook,
-// topic + "|" + UtilAll.getPid()));
-// consumer.setVipChannelEnabled(false);
-// }
-// else {
-// consumer = new DefaultMQPushConsumer(consumerGroup,
-// rocketBinderConfigurationProperties.isEnableMsgTrace(),
-// rocketBinderConfigurationProperties.getCustomizedTraceTopic());
-// }
-//
-// consumer.setNamesrvAddr(RocketMQBinderUtils.getNameServerStr(nameServer));
-// consumer.setConsumeThreadMax(rocketMQConsumerProperties.getConcurrency());
-// consumer.setConsumeThreadMin(rocketMQConsumerProperties.getConcurrency());
-//
-// switch (messageModel) {
-// case BROADCASTING:
-// consumer.setMessageModel(
-// org.apache.rocketmq.common.protocol.heartbeat.MessageModel.BROADCASTING);
-// break;
-// case CLUSTERING:
-// consumer.setMessageModel(
-// org.apache.rocketmq.common.protocol.heartbeat.MessageModel.CLUSTERING);
-// break;
-// default:
-// throw new IllegalArgumentException("Property 'messageModel' was wrong.");
-// }
-//
-// switch (selectorType) {
-// case TAG:
-// consumer.subscribe(topic, selectorExpression);
-// break;
-// case SQL92:
-// consumer.subscribe(topic, MessageSelector.bySql(selectorExpression));
-// break;
-// default:
-// throw new IllegalArgumentException("Property 'selectorType' was wrong.");
-// }
-//
-// switch (consumeMode) {
-// case ORDERLY:
-// consumer.setMessageListener(new DefaultMessageListenerOrderly());
-// break;
-// case CONCURRENTLY:
-// consumer.setMessageListener(new DefaultMessageListenerConcurrently());
-// break;
-// default:
-// throw new IllegalArgumentException("Property 'consumeMode' was wrong.");
-// }
-//
-// if (rocketMQListener instanceof RocketMQPushConsumerLifecycleListener) {
-// ((RocketMQPushConsumerLifecycleListener) rocketMQListener)
-// .prepareStart(consumer);
-// }
-//
-// }
-//
-// @Override
-// public String toString() {
-// return "RocketMQListenerBindingContainer{" + "consumerGroup='" + consumerGroup
-// + '\'' + ", nameServer='" + nameServer + '\'' + ", topic='" + topic + '\''
-// + ", consumeMode=" + consumeMode + ", selectorType=" + selectorType
-// + ", selectorExpression='" + selectorExpression + '\'' + ", messageModel="
-// + messageModel + '}';
-// }
-//
-// public long getSuspendCurrentQueueTimeMillis() {
-// return suspendCurrentQueueTimeMillis;
-// }
-//
-// public void setSuspendCurrentQueueTimeMillis(long suspendCurrentQueueTimeMillis) {
-// this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis;
-// }
-//
-// public int getDelayLevelWhenNextConsume() {
-// return delayLevelWhenNextConsume;
-// }
-//
-// public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) {
-// this.delayLevelWhenNextConsume = delayLevelWhenNextConsume;
-// }
-//
-// public List getNameServer() {
-// return nameServer;
-// }
-//
-// public void setNameServer(List nameServer) {
-// this.nameServer = nameServer;
-// }
-//
-// public String getConsumerGroup() {
-// return consumerGroup;
-// }
-//
-// public void setConsumerGroup(String consumerGroup) {
-// this.consumerGroup = consumerGroup;
-// }
-//
-// public String getTopic() {
-// return topic;
-// }
-//
-// public void setTopic(String topic) {
-// this.topic = topic;
-// }
-//
-// public int getConsumeThreadMax() {
-// return consumeThreadMax;
-// }
-//
-// public void setConsumeThreadMax(int consumeThreadMax) {
-// this.consumeThreadMax = consumeThreadMax;
-// }
-//
-// public String getCharset() {
-// return charset;
-// }
-//
-// public void setCharset(String charset) {
-// this.charset = charset;
-// }
-//
-// public RocketMQListener getRocketMQListener() {
-// return rocketMQListener;
-// }
-//
-// public void setRocketMQListener(RocketMQListener rocketMQListener) {
-// this.rocketMQListener = rocketMQListener;
-// }
-//
-// public DefaultMQPushConsumer getConsumer() {
-// return consumer;
-// }
-//
-// public void setConsumer(DefaultMQPushConsumer consumer) {
-// this.consumer = consumer;
-// }
-//
-// public ExtendedConsumerProperties
-/// getRocketMQConsumerProperties() {
-// return rocketMQConsumerProperties;
-// }
-//
-// public ConsumeMode getConsumeMode() {
-// return consumeMode;
-// }
-//
-// public SelectorType getSelectorType() {
-// return selectorType;
-// }
-//
-// public String getSelectorExpression() {
-// return selectorExpression;
-// }
-//
-// public MessageModel getMessageModel() {
-// return messageModel;
-// }
-//
-// public RocketMQHeaderMapper getHeaderMapper() {
-// return headerMapper;
-// }
-//
-// public void setHeaderMapper(RocketMQHeaderMapper headerMapper) {
-// this.headerMapper = headerMapper;
-// }
-//
-// /**
-// * Convert rocketmq {@link MessageExt} to Spring {@link Message}.
-// * @param messageExt the rocketmq message
-// * @return the converted Spring {@link Message}
-// */
-// @SuppressWarnings("unchecked")
-// private Message convertToSpringMessage(MessageExt messageExt) {
-//
-// // add reconsume-times header to messageExt
-// int reconsumeTimes = messageExt.getReconsumeTimes();
-// messageExt.putUserProperty(ROCKETMQ_RECONSUME_TIMES,
-// String.valueOf(reconsumeTimes));
-// Message message = RocketMQUtil.convertToSpringMessage(messageExt);
-// return MessageBuilder.fromMessage(message)
-// .copyHeaders(headerMapper.toHeaders(messageExt.getProperties())).build();
-// }
-//
-// public class DefaultMessageListenerConcurrently
-// implements MessageListenerConcurrently {
-//
-// @SuppressWarnings({ "unchecked", "Duplicates" })
-// @Override
-// public ConsumeConcurrentlyStatus consumeMessage(List msgs,
-// ConsumeConcurrentlyContext context) {
-// for (MessageExt messageExt : msgs) {
-// log.debug("received msg: {}", messageExt);
-// try {
-// long now = System.currentTimeMillis();
-// rocketMQListener.onMessage(convertToSpringMessage(messageExt));
-// long costTime = System.currentTimeMillis() - now;
-// log.debug("consume {} message key:[{}] cost: {} ms",
-// messageExt.getMsgId(), messageExt.getKeys(), 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", "Duplicates" })
-// @Override
-// public ConsumeOrderlyStatus consumeMessage(List msgs,
-// ConsumeOrderlyContext context) {
-// for (MessageExt messageExt : msgs) {
-// log.debug("received msg: {}", messageExt);
-// try {
-// long now = System.currentTimeMillis();
-// rocketMQListener.onMessage(convertToSpringMessage(messageExt));
-// long costTime = System.currentTimeMillis() - now;
-// log.info("consume {} message key:[{}] cost: {} ms",
-// messageExt.getMsgId(), messageExt.getKeys(), 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/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQMessageQueueChooser.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQMessageQueueChooser.java
deleted file mode 100644
index 948555924e..0000000000
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/consuming/RocketMQMessageQueueChooser.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2013-2018 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://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 com.alibaba.cloud.stream.binder.rocketmq.consuming;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.rocketmq.common.message.MessageQueue;
-
-/**
- * @author Jim
- */
-public class RocketMQMessageQueueChooser {
-
- private volatile int queueIndex = 0;
-
- private volatile List messageQueues;
-
- public MessageQueue choose() {
- return messageQueues.get(queueIndex);
- }
-
- public int requeue() {
- if (queueIndex - 1 < 0) {
- this.queueIndex = messageQueues.size() - 1;
- }
- else {
- this.queueIndex = this.queueIndex - 1;
- }
- return this.queueIndex;
- }
-
- public void increment() {
- this.queueIndex = (this.queueIndex + 1) % messageQueues.size();
- }
-
- public void reset(Set queueSet) {
- this.messageQueues = null;
- this.messageQueues = new ArrayList<>(queueSet);
- this.queueIndex = 0;
- }
-
- public List getMessageQueues() {
- return messageQueues;
- }
-
-}
From 6d7c47a3660de3aa40fd519f52c84947638a4733 Mon Sep 17 00:00:00 2001
From: zkzlx
Date: Mon, 22 Mar 2021 11:05:31 +0800
Subject: [PATCH 05/19] Code refactoring and some new feature support - delete
some invalid files.
---
.../src/main/resources/application.properties | 8 ++--
.../alibaba/cloud/examples/SenderService.java | 4 +-
.../examples/TransactionListenerImpl.java | 38 +++++++++----------
.../src/main/resources/application.properties | 1 +
.../rocketmq/contants/RocketMQConst.java | 13 +------
.../inbound/pull/RocketMQMessageSource.java | 25 +++++++++---
.../RocketMQProducerMessageHandler.java | 2 +-
.../binder/rocketmq/utils/RocketMQUtils.java | 3 +-
.../RocketMQAutoConfigurationTests.java | 22 +++++------
9 files changed, 61 insertions(+), 55 deletions(-)
diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/resources/application.properties
index 2779db5222..e2e77bd0ba 100644
--- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/resources/application.properties
+++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-consume-example/src/main/resources/application.properties
@@ -3,20 +3,20 @@ spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876
spring.cloud.stream.bindings.input1.destination=test-topic
spring.cloud.stream.bindings.input1.content-type=text/plain
spring.cloud.stream.bindings.input1.group=test-group1
-spring.cloud.stream.rocketmq.bindings.input1.consumer.orderly=true
+spring.cloud.stream.rocketmq.bindings.input1.consumer.push.orderly=true
spring.cloud.stream.bindings.input2.destination=test-topic
spring.cloud.stream.bindings.input2.content-type=text/plain
spring.cloud.stream.bindings.input2.group=test-group2
-spring.cloud.stream.rocketmq.bindings.input2.consumer.orderly=false
-spring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tagStr
+spring.cloud.stream.rocketmq.bindings.input2.consumer.push.orderly=false
+spring.cloud.stream.rocketmq.bindings.input2.consumer.subscription=tagStr
spring.cloud.stream.bindings.input2.consumer.concurrency=20
spring.cloud.stream.bindings.input2.consumer.maxAttempts=1
spring.cloud.stream.bindings.input3.destination=test-topic
spring.cloud.stream.bindings.input3.content-type=application/json
spring.cloud.stream.bindings.input3.group=test-group3
-spring.cloud.stream.rocketmq.bindings.input3.consumer.tags=tagObj
+spring.cloud.stream.rocketmq.bindings.input3.consumer.subscription=tagObj
spring.cloud.stream.bindings.input3.consumer.concurrency=20
spring.cloud.stream.bindings.input4.destination=TransactionTopic
diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java
index cd9e50939e..f7db15b574 100644
--- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java
+++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/SenderService.java
@@ -20,8 +20,8 @@
import java.util.stream.Stream;
import com.alibaba.cloud.examples.RocketMQProduceApplication.MySource;
+import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst;
import org.apache.rocketmq.common.message.MessageConst;
-import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
@@ -62,7 +62,7 @@ public void sendTransactionalMsg(T msg, int num) throws Exception {
MessageBuilder builder = MessageBuilder.withPayload(msg)
.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON);
builder.setHeader("test", String.valueOf(num));
- builder.setHeader(RocketMQHeaders.TAGS, "binder");
+ builder.setHeader(RocketMQConst.USER_TRANSACTIONAL_ARGS, "binder");
Message message = builder.build();
source.output2().send(message);
}
diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java
index e58beb2219..1cc1b3290a 100644
--- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java
+++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java
@@ -16,43 +16,43 @@
package com.alibaba.cloud.examples;
-import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
-import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
-import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
-import org.springframework.messaging.Message;
+import org.apache.rocketmq.client.producer.LocalTransactionState;
+import org.apache.rocketmq.client.producer.TransactionListener;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.springframework.stereotype.Component;
/**
* @author Jim
*/
-@RocketMQTransactionListener(txProducerGroup = "myTxProducerGroup", corePoolSize = 5,
- maximumPoolSize = 10)
-public class TransactionListenerImpl implements RocketMQLocalTransactionListener {
+@Component("myTransactionListener")
+public class TransactionListenerImpl implements TransactionListener {
@Override
- public RocketMQLocalTransactionState executeLocalTransaction(Message msg,
- Object arg) {
- Object num = msg.getHeaders().get("test");
+ public LocalTransactionState executeLocalTransaction(Message msg,
+ Object arg) {
+ Object num = msg.getProperty("test");
if ("1".equals(num)) {
System.out.println(
- "executer: " + new String((byte[]) msg.getPayload()) + " unknown");
- return RocketMQLocalTransactionState.UNKNOWN;
+ "executer: " + new String(msg.getBody()) + " unknown");
+ return LocalTransactionState.UNKNOW;
}
else if ("2".equals(num)) {
System.out.println(
- "executer: " + new String((byte[]) msg.getPayload()) + " rollback");
- return RocketMQLocalTransactionState.ROLLBACK;
+ "executer: " + new String(msg.getBody()) + " rollback");
+ return LocalTransactionState.ROLLBACK_MESSAGE;
}
System.out.println(
- "executer: " + new String((byte[]) msg.getPayload()) + " commit");
- return RocketMQLocalTransactionState.COMMIT;
+ "executer: " + new String(msg.getBody()) + " commit");
+ return LocalTransactionState.COMMIT_MESSAGE;
}
@Override
- public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
- System.out.println("check: " + new String((byte[]) msg.getPayload()));
- return RocketMQLocalTransactionState.COMMIT;
+ public LocalTransactionState checkLocalTransaction(MessageExt msg) {
+ System.out.println("check: " + new String(msg.getBody()));
+ return LocalTransactionState.COMMIT_MESSAGE;
}
}
diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties
index 772bf456e3..08ab26ca06 100644
--- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties
+++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/resources/application.properties
@@ -11,6 +11,7 @@ spring.cloud.stream.bindings.output2.destination=TransactionTopic
spring.cloud.stream.bindings.output2.content-type=application/json
spring.cloud.stream.rocketmq.bindings.output2.producer.transactional=true
spring.cloud.stream.rocketmq.bindings.output2.producer.group=myTxProducerGroup
+spring.cloud.stream.rocketmq.bindings.output2.producer.transactionListener=myTransactionListener
spring.cloud.stream.bindings.output3.destination=pull-topic
spring.cloud.stream.bindings.output3.content-type=text/plain
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java
index e83a6a172e..694c8519ca 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java
@@ -18,18 +18,11 @@
import org.apache.rocketmq.common.message.MessageConst;
-import static org.apache.rocketmq.spring.support.RocketMQHeaders.PREFIX;
-
/**
* @author zkzlx
*/
public class RocketMQConst extends MessageConst {
- /**
- * Header key for RocketMQ Transactional Args.
- */
- public static final String ROCKET_TRANSACTIONAL_ARG = "TRANSACTIONAL_ARG";
-
/**
* Default NameServer value.
*/
@@ -38,12 +31,8 @@ public class RocketMQConst extends MessageConst {
/**
* Default group for SCS RocketMQ Binder.
*/
- public static final String DEFAULT_GROUP = PREFIX + "binder_default_group_name";
+ public static final String DEFAULT_GROUP = "binder_default_group_name";
- /**
- * RocketMQ re-consume times.
- */
- public static final String ROCKETMQ_RECONSUME_TIMES = PREFIX + "RECONSUME_TIMES";
public static final String USER_TRANSACTIONAL_ARGS = "TRANSACTIONAL_ARGS";
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java
index 2ca91384b0..a378fc6157 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java
@@ -17,6 +17,7 @@
package com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.pull;
import java.lang.reflect.Field;
+import java.util.Iterator;
import java.util.List;
import com.alibaba.cloud.stream.binder.rocketmq.integration.inbound.RocketMQConsumerFactory;
@@ -62,6 +63,8 @@ public class RocketMQMessageSource extends AbstractMessageSource
private final MessageSelector messageSelector;
private final ExtendedConsumerProperties extendedConsumerProperties;
+ private volatile Iterator messageExtIterator=null;
+
public RocketMQMessageSource(String name,
ExtendedConsumerProperties extendedConsumerProperties) {
this.topic = name;
@@ -82,7 +85,7 @@ public synchronized void start() {
this.consumer = RocketMQConsumerFactory
.initPullConsumer(extendedConsumerProperties);
// This parameter must be 1, otherwise doReceive cannot be handled singly.
- this.consumer.setPullBatchSize(1);
+// this.consumer.setPullBatchSize(1);
this.consumer.subscribe(topic, messageSelector);
this.consumer.setAutoCommit(false);
this.assignedMessageQueue = acquireAssignedMessageQueue(this.consumer);
@@ -132,11 +135,20 @@ public synchronized boolean isRunning() {
@Override
protected synchronized Object doReceive() {
- List messageExtList = consumer.poll();
- if (CollectionUtils.isEmpty(messageExtList) || messageExtList.size() > 1) {
+ if(messageExtIterator == null){
+ List messageExtList = consumer.poll();
+ if (CollectionUtils.isEmpty(messageExtList) || messageExtList.size() > 1) {
+ return null;
+ }
+ messageExtIterator = messageExtList.iterator();
+ }
+ MessageExt messageExt=messageExtIterator.next();
+ if(!messageExtIterator.hasNext()){
+ messageExtIterator = null;
+ }
+ if(null == messageExt){
return null;
}
- MessageExt messageExt = messageExtList.get(0);
MessageQueue messageQueue = null;
for (MessageQueue queue : assignedMessageQueue.getAssignedMessageQueues()) {
if (queue.getQueueId() == messageExt.getQueueId()) {
@@ -144,8 +156,11 @@ protected synchronized Object doReceive() {
break;
}
}
+ if(messageQueue == null){
+ throw new IllegalArgumentException("The message queue is not in assigned list");
+ }
Message message = RocketMQMessageConverterSupport
- .convertMessage2Spring(messageExtList.get(0));
+ .convertMessage2Spring(messageExt);
return MessageBuilder.fromMessage(message)
.setHeader(IntegrationMessageHeaderAccessor.ACKNOWLEDGMENT_CALLBACK,
new RocketMQAckCallback(this.consumer, assignedMessageQueue,
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java
index 66b58f7973..3d58b8af08 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java
@@ -160,7 +160,7 @@ protected void handleMessageInternal(Message> message) {
TransactionListener.class);
if (transactionListener == null) {
throw new MessagingException(
- "TransactionMQProducer must have a TransactionMQProducer !!! ");
+ "TransactionMQProducer must have a TransactionListener !!! ");
}
((TransactionMQProducer) defaultMQProducer)
.setTransactionListener(transactionListener);
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java
index 3f7898422b..85165955d2 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/utils/RocketMQUtils.java
@@ -16,6 +16,7 @@
package com.alibaba.cloud.stream.binder.rocketmq.utils;
+import com.alibaba.cloud.stream.binder.rocketmq.contants.RocketMQConst;
import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;
import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQCommonProperties;
import org.apache.rocketmq.acl.common.AclClientRPCHook;
@@ -81,7 +82,7 @@ public static String getInstanceName(RPCHook rpcHook, String identify) {
public static String getNameServerStr(String nameServer) {
if (StringUtils.isEmpty(nameServer)) {
- return null;
+ return RocketMQConst.DEFAULT_NAME_SERVER;
}
return nameServer.replaceAll(",", ";");
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java
index 8207f98932..02d0de9f95 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/test/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQAutoConfigurationTests.java
@@ -18,7 +18,7 @@
import java.util.Arrays;
-import com.alibaba.cloud.stream.binder.rocketmq.config.RocketMQBinderAutoConfiguration;
+import com.alibaba.cloud.stream.binder.rocketmq.autoconfigurate.RocketMQBinderAutoConfiguration;
import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQBinderConfigurationProperties;
import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQExtendedBindingProperties;
import org.junit.Test;
@@ -37,20 +37,20 @@ public class RocketMQAutoConfigurationTests {
.withConfiguration(
AutoConfigurations.of(RocketMQBinderAutoConfiguration.class))
.withPropertyValues(
- "spring.cloud.stream.rocketmq.binder.name-server[0]=127.0.0.1:9876",
- "spring.cloud.stream.rocketmq.binder.name-server[1]=127.0.0.1:9877",
+ "spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876,127.0.0.1:9877",
"spring.cloud.stream.bindings.output.destination=TopicOrderTest",
"spring.cloud.stream.bindings.output.content-type=application/json",
+
"spring.cloud.stream.bindings.input1.destination=TopicOrderTest",
"spring.cloud.stream.bindings.input1.content-type=application/json",
"spring.cloud.stream.bindings.input1.group=test-group1",
- "spring.cloud.stream.rocketmq.bindings.input1.consumer.orderly=true",
+ "spring.cloud.stream.rocketmq.bindings.input1.consumer.push.orderly=true",
"spring.cloud.stream.bindings.input1.consumer.maxAttempts=1",
"spring.cloud.stream.bindings.input2.destination=TopicOrderTest",
"spring.cloud.stream.bindings.input2.content-type=application/json",
"spring.cloud.stream.bindings.input2.group=test-group2",
- "spring.cloud.stream.rocketmq.bindings.input2.consumer.orderly=false",
- "spring.cloud.stream.rocketmq.bindings.input2.consumer.tags=tag1");
+ "spring.cloud.stream.rocketmq.bindings.input2.consumer.push.orderly=false",
+ "spring.cloud.stream.rocketmq.bindings.input2.consumer.subscription=tag1");
@Test
public void testProperties() {
@@ -58,16 +58,16 @@ public void testProperties() {
RocketMQBinderConfigurationProperties binderConfigurationProperties = context
.getBean(RocketMQBinderConfigurationProperties.class);
assertThat(binderConfigurationProperties.getNameServer())
- .isEqualTo(Arrays.asList("127.0.0.1:9876", "127.0.0.1:9877"));
+ .isEqualTo("127.0.0.1:9876,127.0.0.1:9877");
RocketMQExtendedBindingProperties bindingProperties = context
.getBean(RocketMQExtendedBindingProperties.class);
assertThat(
- bindingProperties.getExtendedConsumerProperties("input2").getTags())
+ bindingProperties.getExtendedConsumerProperties("input2").getSubscription())
.isEqualTo("tag1");
- assertThat(bindingProperties.getExtendedConsumerProperties("input2")
- .getOrderly()).isFalse();
+ assertThat(bindingProperties.getExtendedConsumerProperties("input2").getPush().getOrderly()
+ ).isFalse();
assertThat(bindingProperties.getExtendedConsumerProperties("input1")
- .getOrderly()).isTrue();
+ .getPush().getOrderly()).isTrue();
});
}
From 9379d18ace1a4ca3fb2400920c7e95b17eb4fda9 Mon Sep 17 00:00:00 2001
From: zkzlx
Date: Mon, 22 Mar 2021 14:37:22 +0800
Subject: [PATCH 06/19] Code style
---
.../examples/TransactionListenerImpl.java | 14 +++---
.../RocketMQMessageChannelBinder.java | 7 +--
.../RocketMQBinderAutoConfiguration.java | 4 +-
.../rocketmq/contants/RocketMQConst.java | 33 +++++++++++---
.../convert/RocketMQMessageConverter.java | 14 ++++--
.../custom/RocketMQBeanContainerCache.java | 9 ++--
.../RocketMQConfigBeanPostProcessor.java | 6 +--
.../extend/ErrorAcknowledgeHandler.java | 6 +--
.../inbound/RocketMQConsumerFactory.java | 6 ++-
.../RocketMQInboundChannelAdapter.java | 12 ++---
.../pull/DefaultErrorAcknowledgeHandler.java | 9 ++--
.../inbound/pull/RocketMQAckCallback.java | 13 ++++--
.../inbound/pull/RocketMQMessageSource.java | 21 +++++----
.../outbound/RocketMQProduceFactory.java | 9 +++-
.../RocketMQProducerMessageHandler.java | 24 ++++++----
.../rocketmq/metrics/Instrumentation.java | 14 ++++++
.../metrics/InstrumentationManager.java | 3 ++
...RocketMQBinderConfigurationProperties.java | 5 ++-
.../properties/RocketMQCommonProperties.java | 29 ++++++------
.../RocketMQConsumerProperties.java | 45 ++++++++++---------
.../RocketMQExtendedBindingProperties.java | 4 +-
.../RocketMQProducerProperties.java | 32 ++++++++++---
.../RocketMQSpecificPropertiesProvider.java | 4 +-
.../RocketMQMessageConverterSupport.java | 10 +++--
.../binder/rocketmq/utils/RocketMQUtils.java | 11 ++---
.../RocketMQAutoConfigurationTests.java | 15 +++----
26 files changed, 231 insertions(+), 128 deletions(-)
diff --git a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java
index 1cc1b3290a..446570ec99 100644
--- a/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java
+++ b/spring-cloud-alibaba-examples/rocketmq-example/rocketmq-produce-example/src/main/java/com/alibaba/cloud/examples/TransactionListenerImpl.java
@@ -16,11 +16,11 @@
package com.alibaba.cloud.examples;
-
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
+
import org.springframework.stereotype.Component;
/**
@@ -30,22 +30,18 @@
public class TransactionListenerImpl implements TransactionListener {
@Override
- public LocalTransactionState executeLocalTransaction(Message msg,
- Object arg) {
+ public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
Object num = msg.getProperty("test");
if ("1".equals(num)) {
- System.out.println(
- "executer: " + new String(msg.getBody()) + " unknown");
+ System.out.println("executer: " + new String(msg.getBody()) + " unknown");
return LocalTransactionState.UNKNOW;
}
else if ("2".equals(num)) {
- System.out.println(
- "executer: " + new String(msg.getBody()) + " rollback");
+ System.out.println("executer: " + new String(msg.getBody()) + " rollback");
return LocalTransactionState.ROLLBACK_MESSAGE;
}
- System.out.println(
- "executer: " + new String(msg.getBody()) + " commit");
+ System.out.println("executer: " + new String(msg.getBody()) + " commit");
return LocalTransactionState.COMMIT_MESSAGE;
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java
index 5683bff68e..403f514768 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/RocketMQMessageChannelBinder.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -60,6 +60,7 @@ public class RocketMQMessageChannelBinder extends
ExtendedPropertiesBinder {
private final RocketMQExtendedBindingProperties extendedBindingProperties;
+
private final RocketMQBinderConfigurationProperties binderConfigurationProperties;
public RocketMQMessageChannelBinder(
@@ -175,7 +176,6 @@ protected MessageHandler getPolledConsumerErrorMessageHandler(
/**
* Binders can return an {@link ErrorMessageStrategy} for building error messages;
* binder implementations typically might add extra headers to the error message.
- *
* @return the implementation - may be null.
*/
@Override
@@ -203,4 +203,5 @@ public String getDefaultsPrefix() {
public Class extends BinderSpecificPropertiesProvider> getExtendedPropertiesEntryClass() {
return this.extendedBindingProperties.getExtendedPropertiesEntryClass();
}
+
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java
index abcb9b961a..ec47e951a8 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/autoconfigurate/RocketMQBinderAutoConfiguration.java
@@ -34,7 +34,8 @@
import org.springframework.messaging.converter.CompositeMessageConverter;
/**
- * issue:https://github.com/alibaba/spring-cloud-alibaba/issues/1681
+ * issue:https://github.com/alibaba/spring-cloud-alibaba/issues/1681 .
+ *
* @author Timur Valiev
* @author Jim
*/
@@ -45,6 +46,7 @@ public class RocketMQBinderAutoConfiguration {
@Autowired
private RocketMQExtendedBindingProperties extendedBindingProperties;
+
@Autowired
private RocketMQBinderConfigurationProperties rocketBinderConfigurationProperties;
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java
index 694c8519ca..4f893642ef 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/contants/RocketMQConst.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -31,9 +31,11 @@ public class RocketMQConst extends MessageConst {
/**
* Default group for SCS RocketMQ Binder.
*/
- public static final String DEFAULT_GROUP = "binder_default_group_name";
-
+ public static final String DEFAULT_GROUP = "binder_default_group_name";
+ /**
+ * user args for SCS RocketMQ Binder.
+ */
public static final String USER_TRANSACTIONAL_ARGS = "TRANSACTIONAL_ARGS";
/**
@@ -41,19 +43,34 @@ public class RocketMQConst extends MessageConst {
* and parameters are passed through HEADERS.
*/
public static class Headers {
+
+ /**
+ * keys for SCS RocketMQ Headers.
+ */
public static final String KEYS = MessageConst.PROPERTY_KEYS;
+
+ /**
+ * tags for SCS RocketMQ Headers.
+ */
public static final String TAGS = MessageConst.PROPERTY_TAGS;
+
+ /**
+ * topic for SCS RocketMQ Headers.
+ */
public static final String TOPIC = "MQ_TOPIC";
+
/**
* The ID of the message.
*/
public static final String MESSAGE_ID = "MQ_MESSAGE_ID";
+
/**
* The timestamp that the message producer invokes the message sending API.
*/
public static final String BORN_TIMESTAMP = "MQ_BORN_TIMESTAMP";
+
/**
- * The IP and port number of the message producer
+ * The IP and port number of the message producer.
*/
public static final String BORN_HOST = "MQ_BORN_HOST";
@@ -61,19 +78,23 @@ public static class Headers {
* Message flag, MQ is not processed and is available for use by applications.
*/
public static final String FLAG = "MQ_FLAG";
+
/**
- * Message consumption queue ID
+ * Message consumption queue ID.
*/
public static final String QUEUE_ID = "MQ_QUEUE_ID";
+
/**
* Message system Flag, such as whether or not to compress, whether or not to
* transactional messages.
*/
public static final String SYS_FLAG = "MQ_SYS_FLAG";
+
/**
* The transaction ID of the transaction message.
*/
public static final String TRANSACTION_ID = "MQ_TRANSACTION_ID";
+
}
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java
index 58f17c6efc..98bd032635 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/convert/RocketMQMessageConverter.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -27,14 +27,19 @@
import org.springframework.util.ClassUtils;
/**
- * The default message converter of rocketMq,its bean name is {@link #DEFAULT_NAME}
+ * The default message converter of rocketMq,its bean name is {@link #DEFAULT_NAME} .
+ *
* @author zkzlx
*/
public class RocketMQMessageConverter {
+ /**
+ * rocketMQMessageConverter.
+ */
public static final String DEFAULT_NAME = "rocketMQMessageConverter";
private static final boolean JACKSON_PRESENT;
+
private static final boolean FASTJSON_PRESENT;
static {
@@ -81,4 +86,5 @@ public CompositeMessageConverter getMessageConverter() {
public void setMessageConverter(CompositeMessageConverter messageConverter) {
this.messageConverter = messageConverter;
}
-}
\ No newline at end of file
+
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java
index 9afc948212..21c62aede4 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQBeanContainerCache.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -32,12 +32,15 @@
import org.springframework.util.StringUtils;
/**
- * Gets the beans configured in the configuration file
+ * Gets the beans configured in the configuration file.
*
* @author junboXiang
*/
public final class RocketMQBeanContainerCache {
+ private RocketMQBeanContainerCache() {
+ }
+
private static final Class>[] CLASSES = new Class[] {
CompositeMessageConverter.class, AllocateMessageQueueStrategy.class,
MessageQueueSelector.class, MessageListener.class, TransactionListener.class,
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java
index 30bd643283..a83fdbe08b 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/custom/RocketMQConfigBeanPostProcessor.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -22,7 +22,7 @@
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
- * find RocketMQ bean by annotations
+ * find RocketMQ bean by annotations.
*
* @author junboXiang
*
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java
index fcf6de8045..dfe65fd947 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/extend/ErrorAcknowledgeHandler.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -27,7 +27,7 @@ public interface ErrorAcknowledgeHandler {
/**
* Ack state handling, including receive, reject, and retry, when a consumption
* exception occurs.
- * @param message
+ * @param message message
* @return see {@link Status}
*/
Status handler(Message> message);
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java
index 876249581f..7f7e1bf26a 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQConsumerFactory.java
@@ -41,6 +41,9 @@
*/
public final class RocketMQConsumerFactory {
+ private RocketMQConsumerFactory() {
+ }
+
private final static Logger log = LoggerFactory
.getLogger(RocketMQConsumerFactory.class);
@@ -91,7 +94,8 @@ public static DefaultMQPushConsumer initPushConsumer(
/**
* todo Compatible with versions less than 4.6 ?
- * @return
+ * @param extendedConsumerProperties extendedConsumerProperties
+ * @return DefaultLitePullConsumer
*/
public static DefaultLitePullConsumer initPullConsumer(
ExtendedConsumerProperties extendedConsumerProperties) {
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java
index d0aec55237..61c0eedd33 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/RocketMQInboundChannelAdapter.java
@@ -48,7 +48,6 @@
import org.springframework.util.CollectionUtils;
/**
- * TODO Describe what it does
* @author Jim
*/
public class RocketMQInboundChannelAdapter extends MessageProducerSupport
@@ -58,10 +57,13 @@ public class RocketMQInboundChannelAdapter extends MessageProducerSupport
.getLogger(RocketMQInboundChannelAdapter.class);
private RetryTemplate retryTemplate;
+
private RecoveryCallback recoveryCallback;
+
private DefaultMQPushConsumer pushConsumer;
private final String topic;
+
private final ExtendedConsumerProperties extendedConsumerProperties;
public RocketMQInboundChannelAdapter(String topic,
@@ -146,11 +148,11 @@ public void onError(RetryContext context,
* The actual execution of a user-defined input consumption service method.
* @param messageExtList rocket mq message list
* @param failSupplier {@link ConsumeConcurrentlyStatus} or
- * {@link ConsumeOrderlyStatus}
+ * {@link ConsumeOrderlyStatus}
* @param sucSupplier {@link ConsumeConcurrentlyStatus} or
- * {@link ConsumeOrderlyStatus}
- * @param
- * @return
+ * {@link ConsumeOrderlyStatus}
+ * @param object
+ * @return R
*/
private R consumeMessage(List messageExtList,
Supplier failSupplier, Supplier sucSupplier) {
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java
index 3296a128e9..458324741b 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/DefaultErrorAcknowledgeHandler.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -29,15 +29,16 @@
* @author zkzlx
*/
public class DefaultErrorAcknowledgeHandler implements ErrorAcknowledgeHandler {
+
/**
* Ack state handling, including receive, reject, and retry, when a consumption
* exception occurs.
- *
- * @param message
+ * @param message message
* @return see {@link Status}
*/
@Override
public Status handler(Message> message) {
return Status.REQUEUE;
}
+
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java
index f617dd097e..56e50ca4a5 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQAckCallback.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -31,16 +31,23 @@
/**
* A pollable {@link org.springframework.integration.core.MessageSource} for RocketMQ.
+ *
* @author zkzlx
*/
public class RocketMQAckCallback implements AcknowledgmentCallback {
+
private final static Logger log = LoggerFactory.getLogger(RocketMQAckCallback.class);
private boolean acknowledged;
+
private boolean autoAckEnabled = true;
+
private MessageExt messageExt;
+
private AssignedMessageQueue assignedMessageQueue;
+
private DefaultLitePullConsumer consumer;
+
private final MessageQueue messageQueue;
public RocketMQAckCallback(DefaultLitePullConsumer consumer,
@@ -109,4 +116,4 @@ public void acknowledge(Status status) {
}
}
-}
\ No newline at end of file
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java
index a378fc6157..a7d7e73da1 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/inbound/pull/RocketMQMessageSource.java
@@ -56,14 +56,18 @@ public class RocketMQMessageSource extends AbstractMessageSource
.getLogger(RocketMQMessageSource.class);
private DefaultLitePullConsumer consumer;
+
private AssignedMessageQueue assignedMessageQueue;
+
private volatile boolean running;
private final String topic;
+
private final MessageSelector messageSelector;
+
private final ExtendedConsumerProperties extendedConsumerProperties;
- private volatile Iterator messageExtIterator=null;
+ private volatile Iterator messageExtIterator = null;
public RocketMQMessageSource(String name,
ExtendedConsumerProperties extendedConsumerProperties) {
@@ -85,7 +89,7 @@ public synchronized void start() {
this.consumer = RocketMQConsumerFactory
.initPullConsumer(extendedConsumerProperties);
// This parameter must be 1, otherwise doReceive cannot be handled singly.
-// this.consumer.setPullBatchSize(1);
+ // this.consumer.setPullBatchSize(1);
this.consumer.subscribe(topic, messageSelector);
this.consumer.setAutoCommit(false);
this.assignedMessageQueue = acquireAssignedMessageQueue(this.consumer);
@@ -135,18 +139,18 @@ public synchronized boolean isRunning() {
@Override
protected synchronized Object doReceive() {
- if(messageExtIterator == null){
+ if (messageExtIterator == null) {
List messageExtList = consumer.poll();
if (CollectionUtils.isEmpty(messageExtList) || messageExtList.size() > 1) {
return null;
}
messageExtIterator = messageExtList.iterator();
}
- MessageExt messageExt=messageExtIterator.next();
- if(!messageExtIterator.hasNext()){
+ MessageExt messageExt = messageExtIterator.next();
+ if (!messageExtIterator.hasNext()) {
messageExtIterator = null;
}
- if(null == messageExt){
+ if (null == messageExt) {
return null;
}
MessageQueue messageQueue = null;
@@ -156,8 +160,9 @@ protected synchronized Object doReceive() {
break;
}
}
- if(messageQueue == null){
- throw new IllegalArgumentException("The message queue is not in assigned list");
+ if (messageQueue == null) {
+ throw new IllegalArgumentException(
+ "The message queue is not in assigned list");
}
Message message = RocketMQMessageConverterSupport
.convertMessage2Spring(messageExt);
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java
index 7017ba46e2..4638684384 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProduceFactory.java
@@ -39,18 +39,23 @@
import org.springframework.util.StringUtils;
/**
- * Extended function related to producer . eg:initial
+ * Extended function related to producer . eg:initial .
*
* @author zkzlx
*/
public final class RocketMQProduceFactory {
+ private RocketMQProduceFactory() {
+ }
+
private final static Logger log = LoggerFactory
.getLogger(RocketMQProduceFactory.class);
/**
* init for the producer,including convert producer params.
- * @return
+ * @param topic topic
+ * @param producerProperties producerProperties
+ * @return DefaultMQProducer
*/
public static DefaultMQProducer initRocketMQProducer(String topic,
RocketMQProducerProperties producerProperties) {
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java
index 3d58b8af08..56c2087597 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/integration/outbound/RocketMQProducerMessageHandler.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -61,16 +61,23 @@ public class RocketMQProducerMessageHandler extends AbstractMessageHandler
.getLogger(RocketMQProducerMessageHandler.class);
private volatile boolean running = false;
+
private volatile boolean isTrans = false;
private ErrorMessageStrategy errorMessageStrategy;
+
private MessageChannel sendFailureChannel;
+
private MessageConverterConfigurer.PartitioningInterceptor partitioningInterceptor;
+
private DefaultMQProducer defaultMQProducer;
+
private MessageQueueSelector messageQueueSelector;
private final ProducerDestination destination;
+
private final ExtendedProducerProperties extendedProducerProperties;
+
private final RocketMQProducerProperties mqProducerProperties;
public RocketMQProducerMessageHandler(ProducerDestination destination,
@@ -93,10 +100,8 @@ protected void onInit() {
// Use the default if the partition is on and no customization is available.
this.messageQueueSelector = RocketMQBeanContainerCache.getBean(
mqProducerProperties.getMessageQueueSelector(),
- MessageQueueSelector.class,
- extendedProducerProperties.isPartitioned()
- ? new PartitionMessageQueueSelector()
- : null);
+ MessageQueueSelector.class, extendedProducerProperties.isPartitioned()
+ ? new PartitionMessageQueueSelector() : null);
}
@Override
@@ -226,9 +231,9 @@ private SendResult send(org.apache.rocketmq.common.message.Message mqMessage,
}
/**
- * https://github.com/alibaba/spring-cloud-alibaba/issues/1408
- * @param message
- * @return
+ * https://github.com/alibaba/spring-cloud-alibaba/issues/1408 .
+ * @param message message
+ * @return SendCallback
*/
private SendCallback getSendCallback(Message> message) {
SendCallback sendCallback = RocketMQBeanContainerCache
@@ -283,4 +288,5 @@ public RocketMQProducerMessageHandler setPartitioningInterceptor(
this.partitioningInterceptor = partitioningInterceptor;
return this;
}
+
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java
index 397e628543..e264828550 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/Instrumentation.java
@@ -28,6 +28,7 @@
public class Instrumentation {
private final String name;
+
private Lifecycle actuator;
protected final AtomicBoolean started = new AtomicBoolean(false);
@@ -88,4 +89,17 @@ public Exception getStartException() {
public int hashCode() {
return Objects.hash(getName(), getActuator());
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Instrumentation that = (Instrumentation) o;
+ return name.equals(that.name) && actuator.equals(that.actuator);
+ }
+
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java
index de6e1e794c..ad7958e447 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/metrics/InstrumentationManager.java
@@ -26,6 +26,9 @@
*/
public final class InstrumentationManager {
+ private InstrumentationManager() {
+ }
+
private static final Map HEALTH_INSTRUMENTATIONS = new HashMap<>();
public static Collection getHealthInstrumentations() {
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java
index fd5e77919b..3da04ea184 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQBinderConfigurationProperties.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -20,6 +20,7 @@
/**
* binding rocketMq properties.
+ *
* @author Jim
*/
@ConfigurationProperties(prefix = "spring.cloud.stream.rocketmq.binder")
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java
index 00e7d30dd7..9e91146412 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQCommonProperties.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -26,6 +26,7 @@
* @author zkzlx
*/
public class RocketMQCommonProperties implements Serializable {
+
private static final long serialVersionUID = -6724870154343284715L;
private boolean enabled = true;
@@ -41,38 +42,36 @@ public class RocketMQCommonProperties implements Serializable {
* The property of "secret-key".
*/
private String secretKey;
+
/**
* Consumers of the same role is required to have exactly same subscriptions and
* consumerGroup to correctly achieve load balance. It's required and needs to be
- * globally unique.
- *
- * Producer group conceptually aggregates all producer instances of exactly same role,
- * which is particularly important when transactional messages are involved.
- *
- *
- * For non-transactional messages, it does not matter as long as it's unique per
- * process.
- *
- *
- * See here for further
- * discussion.
+ * globally unique. Producer group conceptually aggregates all producer instances of
+ * exactly same role, which is particularly important when transactional messages are
+ * involved. For non-transactional messages, it does not matter as long as it's unique
+ * per process. See here
+ * for further discussion.
*/
private String group;
private String namespace;
+
private String accessChannel = AccessChannel.LOCAL.name();
+
/**
* Pulling topic information interval from the named server.
* see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask
* updateTopicRouteInfoFromNameServer.
*/
private int pollNameServerInterval = 1000 * 30;
+
/**
* Heartbeat interval in microseconds with message broker.
* see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask
* sendHeartbeatToAllBroker .
*/
private int heartbeatBrokerInterval = 1000 * 30;
+
/**
* Offset persistent interval for consumer.
* see{@link MQClientInstance#startScheduledTask()},eg:ScheduledTask
@@ -85,6 +84,7 @@ public class RocketMQCommonProperties implements Serializable {
private boolean useTLS = TlsSystemConfig.tlsEnable;
private boolean enableMsgTrace = true;
+
private String customizedTraceTopic;
public boolean getEnabled() {
@@ -198,4 +198,5 @@ public String getCustomizedTraceTopic() {
public void setCustomizedTraceTopic(String customizedTraceTopic) {
this.customizedTraceTopic = customizedTraceTopic;
}
+
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java
index 1a889f6d7d..ebe2c1c435 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQConsumerProperties.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -37,8 +37,6 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties {
/**
* Message model defines the way how messages are delivered to each consumer clients.
- *
- *
* This field defaults to clustering.
*/
private String messageModel = MessageModel.CLUSTERING.getModeCN();
@@ -60,13 +58,12 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties {
private String subscription;
/**
- * Delay some time when exception occur
+ * Delay some time when exception occur .
*/
private long pullTimeDelayMillsWhenException = 1000;
/**
* Consuming point on consumer booting.
- *
*
* There are three consuming points:
*
@@ -90,6 +87,7 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties {
*
*/
private ConsumeFromWhere consumeFromWhere = ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET;
+
/**
* Backtracking consumption time with second precision. Time format is
* 20131223171201
@@ -102,13 +100,14 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties {
/**
* Flow control threshold on queue level, each message queue will cache at most 1000
* messages by default, Consider the {@link #pullBatchSize}, the instantaneous value
- * may exceed the limit
+ * may exceed the limit .
*/
private int pullThresholdForQueue = 1000;
+
/**
* Limit the cached message size on queue level, each message queue will cache at most
* 100 MiB messages by default, Consider the {@link #pullBatchSize}, the instantaneous
- * value may exceed the limit
+ * value may exceed the limit .
*
*
* The size of a message only measured by message body, so it's not accurate
@@ -126,6 +125,7 @@ public class RocketMQConsumerProperties extends RocketMQCommonProperties {
private int consumeMaxSpan = 2000;
private Push push = new Push();
+
private Pull pull = new Pull();
public String getMessageModel() {
@@ -238,6 +238,7 @@ public RocketMQConsumerProperties setConsumeMaxSpan(int consumeMaxSpan) {
}
public static class Push implements Serializable {
+
private static final long serialVersionUID = -7398468554978817630L;
/**
@@ -245,6 +246,7 @@ public static class Push implements Serializable {
* false, using {@link MessageListenerConcurrently}.
*/
private boolean orderly = false;
+
/**
* Suspending pulling time for cases requiring slow pulling like flow-control
* scenario. see{@link ConsumeMessageOrderlyService#processConsumeResult}.
@@ -254,10 +256,9 @@ public static class Push implements Serializable {
/**
* https://github.com/alibaba/spring-cloud-alibaba/issues/1866 Max re-consume
- * times. -1 means 16 times.
- *
- * If messages are re-consumed more than {@link #maxReconsumeTimes} before
- * success, it's be directed to a deletion queue waiting.
+ * times. -1 means 16 times. If messages are re-consumed more than
+ * {@link #maxReconsumeTimes} before success, it's be directed to a deletion queue
+ * waiting.
*/
private int maxReconsumeTimes;
@@ -285,21 +286,21 @@ public static class Push implements Serializable {
* MiB(Unlimited)
*
* The value of {@code pullThresholdSizeForQueue} will be overwrote and calculated
- * based on {@code pullThresholdSizeForTopic} if it is't unlimited
+ * based on {@code pullThresholdSizeForTopic} if it is't unlimited .
*
* For example, if the value of pullThresholdSizeForTopic is 1000 MiB and 10
* message queues are assigned to this consumer, then pullThresholdSizeForQueue
- * will be set to 100 MiB
+ * will be set to 100 MiB .
*/
private int pullThresholdSizeForTopic = -1;
/**
- * Message pull Interval
+ * Message pull Interval.
*/
private long pullInterval = 0;
/**
- * Batch consumption size
+ * Batch consumption size.
*/
private int consumeMessageBatchMaxSize = 1;
@@ -366,15 +367,18 @@ public int getConsumeMessageBatchMaxSize() {
public void setConsumeMessageBatchMaxSize(int consumeMessageBatchMaxSize) {
this.consumeMessageBatchMaxSize = consumeMessageBatchMaxSize;
}
+
}
public static class Pull implements Serializable {
+
/**
- * The poll timeout in milliseconds
+ * The poll timeout in milliseconds.
*/
private long pollTimeoutMillis = 1000 * 5;
+
/**
- * Pull thread number
+ * Pull thread number.
*/
private int pullThreadNums = 20;
@@ -385,13 +389,13 @@ public static class Pull implements Serializable {
/**
* Long polling mode, the Consumer connection timeout(must greater than
- * brokerSuspendMaxTimeMillis), it is not recommended to modify
+ * brokerSuspendMaxTimeMillis), it is not recommended to modify.
*/
private long consumerTimeoutMillisWhenSuspend = 1000 * 30;
/**
* Ack state handling, including receive, reject, and retry, when a consumption
- * exception occurs. see {@link }
+ * exception occurs.
*/
private String errAcknowledge;
@@ -446,6 +450,7 @@ public long getPullThresholdForAll() {
public void setPullThresholdForAll(long pullThresholdForAll) {
this.pullThresholdForAll = pullThresholdForAll;
}
+
}
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java
index 5fc34ed087..6c4af119d9 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQExtendedBindingProperties.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java
index 8f73cf93f4..4035f14834 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq/src/main/java/com/alibaba/cloud/stream/binder/rocketmq/properties/RocketMQProducerProperties.java
@@ -1,11 +1,11 @@
/*
- * Copyright (C) 2018 the original author or authors.
+ * Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://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,
@@ -37,7 +37,6 @@ public class RocketMQProducerProperties extends RocketMQCommonProperties {
/**
* Maximum number of retry to perform internally before claiming sending failure in
* synchronous mode.
- *