This is an automated email from the ASF dual-hosted git repository.
jinrongtong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-e2e.git
The following commit(s) were added to refs/heads/master by this push:
new 998bcfe [ISSUE #13] Add End-to-end (e2e) test cases for RocketMQ
Spring client (#14)
998bcfe is described below
commit 998bcfec7012e25987579fd9d0038c69a3387488
Author: yueya <[email protected]>
AuthorDate: Wed Apr 12 11:06:16 2023 +0800
[ISSUE #13] Add End-to-end (e2e) test cases for RocketMQ Spring client (#14)
* Update README.md
* Update README.md
* Update pom
* End-to-end (e2e) test cases for RocketMQ Spring client support.
---------
Co-authored-by: 月伢 <[email protected]>
---
README.md | 2 +-
java/e2e-spring/pom.xml | 80 +++++++
.../org/apache/rocketmq/RocketMQApplication.java | 20 ++
.../apache/rocketmq/client/DelayListenerImpl.java | 45 ++++
.../org/apache/rocketmq/client/MQAdminTools.java | 62 +++++
.../apache/rocketmq/client/NormalListenerImpl.java | 41 ++++
.../apache/rocketmq/client/OrderListenerImpl.java | 49 ++++
.../rocketmq/client/TransactionListenerImpl.java | 48 ++++
.../java/org/apache/rocketmq/utils/MQAdmin.java | 251 +++++++++++++++++++++
.../org/apache/rocketmq/utils/RandomUtils.java | 91 ++++++++
.../java/org/apache/rocketmq/utils/TestUtils.java | 137 +++++++++++
.../src/main/resources/application.properties | 32 +++
.../org/apache/rocketmq/SpringBootBaseTest.java | 32 +++
.../apache/rocketmq/message/DelayMessageTest.java | 94 ++++++++
.../apache/rocketmq/message/NormalMessageTest.java | 101 +++++++++
.../apache/rocketmq/message/OrderMessageTest.java | 75 ++++++
.../apache/rocketmq/message/TransMessageTest.java | 113 ++++++++++
.../src/test/resources/junit-platform.properties | 19 ++
.../e2e-spring/src/test/resources/log4j.properties | 25 ++
.../e2e-spring/src/test/resources/logback-test.xml | 35 +++
java/e2e-v4/pom.xml | 42 +++-
.../rocketmq/server/delay/DelayMessageTest.java | 2 +-
.../rocketmq/server/normal/NormalMessageTest.java | 2 +-
.../rocketmq/server/order/OrderMessageTest.java | 2 +-
.../server/transaction/TransactionMessageTest.java | 2 +-
java/e2e/pom.xml | 39 ++++
java/pom.xml | 147 ++++++++----
pom.xml | 1 +
28 files changed, 1542 insertions(+), 47 deletions(-)
diff --git a/README.md b/README.md
index 5f166dd..d37fc5f 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
## Apache RocketMQ E2E
[](https://www.apache.org/licenses/LICENSE-2.0.html)
-RocketMQ E2E Test
+RocketMQ E2E Test
### Test Case Coverage
* Message Type
diff --git a/java/e2e-spring/pom.xml b/java/e2e-spring/pom.xml
new file mode 100644
index 0000000..c088d86
--- /dev/null
+++ b/java/e2e-spring/pom.xml
@@ -0,0 +1,80 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.rocketmq</groupId>
+ <artifactId>rocketmq-java-test</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>rocketmq-java-spring-boot-e2e</artifactId>
+
+ <properties>
+ <spring.boot.starter.version>2.7.8</spring.boot.starter.version>
+ <rocketmq.spring.boot.version>2.2.3</rocketmq.spring.boot.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.rocketmq</groupId>
+ <artifactId>rocketmq-spring-boot-starter</artifactId>
+ <version>${rocketmq.spring.boot.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.rocketmq</groupId>
+ <artifactId>rocketmq-tools</artifactId>
+ <version>5.0.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <version>${spring.boot.starter.version}</version>
+<!-- <scope>test</scope>-->
+ <exclusions>
+ <exclusion>
+ <groupId>org.junit.vintage</groupId>
+ <artifactId>junit-vintage-engine</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>3.0.2</version>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/*.conf</include>
+ <include>**/*.properties</include>
+ </includes>
+ </resource>
+ </resources>
+ </build>
+</project>
\ No newline at end of file
diff --git
a/java/e2e-spring/src/main/java/org/apache/rocketmq/RocketMQApplication.java
b/java/e2e-spring/src/main/java/org/apache/rocketmq/RocketMQApplication.java
new file mode 100644
index 0000000..5955f9e
--- /dev/null
+++ b/java/e2e-spring/src/main/java/org/apache/rocketmq/RocketMQApplication.java
@@ -0,0 +1,20 @@
+package org.apache.rocketmq;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
+public class RocketMQApplication {
+ protected static List<String> nameserverIpList = new ArrayList<>();
+ protected static String nameserverPort = "9876";
+
+ public static void main(String[] args) {
+ SpringApplication.run(RocketMQApplication.class, args);
+ }
+}
diff --git
a/java/e2e-spring/src/main/java/org/apache/rocketmq/client/DelayListenerImpl.java
b/java/e2e-spring/src/main/java/org/apache/rocketmq/client/DelayListenerImpl.java
new file mode 100644
index 0000000..77535ff
--- /dev/null
+++
b/java/e2e-spring/src/main/java/org/apache/rocketmq/client/DelayListenerImpl.java
@@ -0,0 +1,45 @@
+package org.apache.rocketmq.client;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.common.attribute.TopicMessageType;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.apache.rocketmq.utils.MQAdmin;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.HashMap;
+import java.util.LinkedList;
+import org.springframework.core.env.Environment;
+@Slf4j
+@Component
+@RocketMQMessageListener(topic = "${rocketmq.test.topic.delay}", consumerGroup
= "gid-delay-spring-test", selectorExpression = "*")
+public class DelayListenerImpl implements RocketMQListener<MessageExt> {
+
+ // <MessageId, ReceivedTime>
+ private HashMap<String, Long> receivedMessages = new HashMap<>();
+ private LinkedList<String> receivedMessageIds = new LinkedList<>();
+ private String lastMessage;
+
+ @Override
+ public void onMessage(MessageExt msg) {
+ log.info("Received message: " + msg);
+ lastMessage = msg.getMsgId();
+ receivedMessages.put(msg.getMsgId(), System.currentTimeMillis());
+ receivedMessageIds.add(msg.getMsgId());
+ }
+
+ public String getLastMessage() {
+ return lastMessage;
+ }
+
+ public HashMap<String, Long> getReceivedMessages() {
+ return receivedMessages;
+ }
+
+ public LinkedList<String> getReceivedMessageIds() {
+ return receivedMessageIds;
+ }
+}
diff --git
a/java/e2e-spring/src/main/java/org/apache/rocketmq/client/MQAdminTools.java
b/java/e2e-spring/src/main/java/org/apache/rocketmq/client/MQAdminTools.java
new file mode 100644
index 0000000..8397377
--- /dev/null
+++ b/java/e2e-spring/src/main/java/org/apache/rocketmq/client/MQAdminTools.java
@@ -0,0 +1,62 @@
+package org.apache.rocketmq.client;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.common.attribute.TopicMessageType;
+import org.apache.rocketmq.utils.MQAdmin;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Component
+public class MQAdminTools {
+ protected static List<String> nameserverIpList = new ArrayList<>();
+ protected static String nameserverPort = "9876";
+ @Value("${rocketmq.name-server}")
+ private String nameserver;
+ @Value("${rocketmq.cluster}")
+ private String cluster;
+ @Value("${rocketmq.test.topic.normal}")
+ private String normalTopic;
+ @Value("${rocketmq.test.topic.delay}")
+ private String delayTopic;
+ @Value("${rocketmq.test.topic.order}")
+ private String orderTopic;
+ @Value("${rocketmq.test.topic.trans}")
+ private String transTopic;
+
+ @PostConstruct
+ private void init() {
+ MQAdmin.initMQAdminExtInstance(nameserver);
+ boolean result1 = MQAdmin.createTopic(cluster, normalTopic, 8,
TopicMessageType.NORMAL.getValue());
+ boolean result2 = MQAdmin.createTopic(cluster, delayTopic, 8,
TopicMessageType.NORMAL.getValue());
+ boolean result3 = MQAdmin.createTopic(cluster, orderTopic, 8,
TopicMessageType.NORMAL.getValue());
+ boolean result4 = MQAdmin.createTopic(cluster, transTopic, 8,
TopicMessageType.NORMAL.getValue());
+ log.info("Create topic[{}] {}", normalTopic, result1);
+ log.info("Create topic[{}] {}", normalTopic, result2);
+ log.info("Create topic[{}] {}", normalTopic, result3);
+ log.info("Create topic[{}] {}", normalTopic, result4);
+ }
+
+// private static void initConnectionInfo() {
+// String ALL_IP = System.getProperty("ALL_IP");
+// if (ALL_IP != null) {
+// String[] allPodInfos = ALL_IP.split(",");
+// for (String podInfo : allPodInfos) {
+// if (podInfo.contains("nameserver")) {
+//
nameserverIpList.add(podInfo.substring(podInfo.indexOf(":") + 1));
+// }
+// }
+// if (nameserverIpList.isEmpty()) {
+// log.warn("INIT- Get nameserver from external is empty");
+// } else {
+// String namesrvAddr = nameserverIpList.get(0) + ":" +
nameserverPort;
+// System.setProperty("rocketmq.name-server", namesrvAddr);
+// }
+// }
+// }
+
+}
diff --git
a/java/e2e-spring/src/main/java/org/apache/rocketmq/client/NormalListenerImpl.java
b/java/e2e-spring/src/main/java/org/apache/rocketmq/client/NormalListenerImpl.java
new file mode 100644
index 0000000..fe6ec89
--- /dev/null
+++
b/java/e2e-spring/src/main/java/org/apache/rocketmq/client/NormalListenerImpl.java
@@ -0,0 +1,41 @@
+package org.apache.rocketmq.client;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+
+@Slf4j
+@Component
+@RocketMQMessageListener(topic = "${rocketmq.test.topic.normal}",
consumerGroup = "gid-normal-spring-test", selectorExpression = "*")
+public class NormalListenerImpl implements RocketMQListener<MessageExt> {
+
+ private HashMap<String, String> receivedMessages = new HashMap<>();
+ private LinkedList<String> receivedMessageIds = new LinkedList<>();
+ private String lastMessage;
+
+ @Override
+ public void onMessage(MessageExt msg) {
+ log.info("Received message: " + msg);
+ lastMessage = msg.getMsgId();
+ log.info("Received messageId: " + msg.getMsgId());
+ receivedMessages.put(msg.getMsgId(), new String(msg.getBody()));
+ receivedMessageIds.add(msg.getMsgId());
+ }
+
+ public String getLastMessage() {
+ return lastMessage;
+ }
+
+ public HashMap<String, String> getReceivedMessages() {
+ return receivedMessages;
+ }
+
+ public LinkedList<String> getReceivedMessageIds() {
+ return receivedMessageIds;
+ }
+}
diff --git
a/java/e2e-spring/src/main/java/org/apache/rocketmq/client/OrderListenerImpl.java
b/java/e2e-spring/src/main/java/org/apache/rocketmq/client/OrderListenerImpl.java
new file mode 100644
index 0000000..1fd473c
--- /dev/null
+++
b/java/e2e-spring/src/main/java/org/apache/rocketmq/client/OrderListenerImpl.java
@@ -0,0 +1,49 @@
+package org.apache.rocketmq.client;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.spring.annotation.ConsumeMode;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.springframework.stereotype.Component;
+
+import java.util.LinkedList;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Slf4j
+@Component
+@RocketMQMessageListener(topic = "${rocketmq.test.topic.order}", consumerGroup
= "gid-order-spring-test", selectorExpression = "*", consumeMode =
ConsumeMode.ORDERLY)
+public class OrderListenerImpl implements RocketMQListener<MessageExt> {
+
+ private ConcurrentHashMap<String, LinkedList<MessageExt>> messageGroups =
new ConcurrentHashMap<>();
+ private LinkedList<String> receivedMessageIds = new LinkedList<>();
+ private String lastMessage;
+
+ @Override
+ public void onMessage(MessageExt msg) {
+ log.info("Received message- queueId:{}, msgId:{}, body:{}",
msg.getQueueId(), msg.getMsgId(), new String(msg.getBody()));
+ lastMessage = msg.getMsgId();
+ String shardingKey = String.valueOf(msg.getQueueId());
+ LinkedList<MessageExt> messages = new LinkedList<>();
+ if (messageGroups.containsKey(shardingKey)) {
+ messages = messageGroups.get(shardingKey);
+ messages.add(msg);
+ } else {
+ messages.add(msg);
+ messageGroups.put(shardingKey, messages);
+ }
+ receivedMessageIds.add(msg.getMsgId());
+ }
+
+ public String getLastMessage() {
+ return lastMessage;
+ }
+
+ public ConcurrentHashMap<String, LinkedList<MessageExt>>
getMessageGroups() {
+ return messageGroups;
+ }
+
+ public LinkedList<String> getReceivedMessageIds() {
+ return receivedMessageIds;
+ }
+}
diff --git
a/java/e2e-spring/src/main/java/org/apache/rocketmq/client/TransactionListenerImpl.java
b/java/e2e-spring/src/main/java/org/apache/rocketmq/client/TransactionListenerImpl.java
new file mode 100644
index 0000000..4b6716a
--- /dev/null
+++
b/java/e2e-spring/src/main/java/org/apache/rocketmq/client/TransactionListenerImpl.java
@@ -0,0 +1,48 @@
+package org.apache.rocketmq.client;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
+import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
+import org.springframework.messaging.Message;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+
+@Slf4j
+@Component
+@RocketMQTransactionListener
+public class TransactionListenerImpl implements
RocketMQLocalTransactionListener {
+
+ private HashMap<String, String> receivedMessages = new HashMap<>();
+ private LinkedList<String> receivedMessageIds = new LinkedList<>();
+ private String lastMessage;
+
+ private RocketMQLocalTransactionState executeState =
RocketMQLocalTransactionState.COMMIT;
+ private RocketMQLocalTransactionState checkState =
RocketMQLocalTransactionState.COMMIT;
+
+ @Override
+ public RocketMQLocalTransactionState executeLocalTransaction(Message
message, Object o) {
+ log.info(message.toString());
+ return executeState;
+ }
+
+ @Override
+ public RocketMQLocalTransactionState checkLocalTransaction(Message
message) {
+ return checkState;
+ }
+
+ public void setExecuteState(RocketMQLocalTransactionState executeState) {
+ log.info("executor state: {}", executeState);
+ this.executeState = executeState;
+ }
+
+ public void setCheckState(RocketMQLocalTransactionState checkState) {
+ log.info("check state: {}", checkState);
+ this.checkState = checkState;
+ }
+}
diff --git
a/java/e2e-spring/src/main/java/org/apache/rocketmq/utils/MQAdmin.java
b/java/e2e-spring/src/main/java/org/apache/rocketmq/utils/MQAdmin.java
new file mode 100644
index 0000000..2c3e196
--- /dev/null
+++ b/java/e2e-spring/src/main/java/org/apache/rocketmq/utils/MQAdmin.java
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.utils;
+
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.common.TopicAttributes;
+import org.apache.rocketmq.common.admin.ConsumeStats;
+import org.apache.rocketmq.common.admin.TopicStatsTable;
+import org.apache.rocketmq.common.protocol.body.ClusterInfo;
+import org.apache.rocketmq.common.protocol.route.BrokerData;
+import org.apache.rocketmq.common.subscription.SubscriptionGroupConfig;
+import org.apache.rocketmq.tools.admin.DefaultMQAdminExt;
+import org.apache.rocketmq.tools.command.CommandUtil;
+import org.junit.jupiter.api.Assertions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.UUID;
+
+public class MQAdmin {
+ private static final Logger log = LoggerFactory.getLogger(MQAdmin.class);
+ public static DefaultMQAdminExt mqAdminExt;
+
+ public static DefaultMQAdminExt initMQAdminExtInstance(String namesrvAddr)
{
+ mqAdminExt = new DefaultMQAdminExt();
+ mqAdminExt.setInstanceName(UUID.randomUUID().toString());
+ mqAdminExt.setNamesrvAddr(namesrvAddr);
+ try {
+ mqAdminExt.start();
+ } catch (MQClientException e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ return mqAdminExt;
+ }
+
+ public static boolean createTopic(String clusterName, String topic, int
queueNum) {
+ int defaultWaitTime = 30;
+ Map<String, String> attributes = new HashMap<>();
+ return createTopic(clusterName, topic, queueNum, attributes,
defaultWaitTime);
+ }
+
+ public static boolean createTopic(String clusterName, String topic, int
queueNum, String type) {
+ int defaultWaitTime = 30;
+ Map<String, String> attributes = new HashMap<>();
+ attributes.put("+" +
TopicAttributes.TOPIC_MESSAGE_TYPE_ATTRIBUTE.getName(), type);
+ return createTopic(clusterName, topic, queueNum, attributes,
defaultWaitTime);
+ }
+
+ public static boolean createTopic(String clusterName, String topic, int
queueNum, Map<String, String> attributes,
+ int waitTimeSec) {
+ boolean createResult = false;
+ try {
+ mqAdminExt.createTopic(clusterName, topic, queueNum, attributes);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ long startTime = System.currentTimeMillis();
+ while (!createResult) {
+ createResult = checkTopicExist(mqAdminExt, topic);
+ if (System.currentTimeMillis() - startTime < waitTimeSec * 1000) {
+ TestUtils.waitForMoment(100);
+ } else {
+ log.error(String.format("timeout,but create topic[%s]
failed!", topic));
+ break;
+ }
+ }
+ if (createResult) {
+ log.info("create topic:{} success", topic);
+ }
+ return createResult;
+ }
+
+ public static boolean createConsumerGroup(String clusterName, String
groupId, int waitTimeSec) {
+ boolean createResult = false;
+ try {
+ SubscriptionGroupConfig subscriptionGroupConfig = new
SubscriptionGroupConfig();
+ subscriptionGroupConfig.setConsumeBroadcastEnable(false);
+ subscriptionGroupConfig.setConsumeFromMinEnable(false);
+ subscriptionGroupConfig.setGroupName(groupId);
+ subscriptionGroupConfig.setConsumeMessageOrderly(true);
+
+ Set<String> masterSet =
CommandUtil.fetchMasterAddrByClusterName(mqAdminExt, clusterName);
+ for (String addr : masterSet) {
+ mqAdminExt.createAndUpdateSubscriptionGroupConfig(addr,
subscriptionGroupConfig);
+ log.info(String.format("create subscription group %s to %s
success.\n", groupId, addr));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Assertions.fail(String.format("create groupId:%s failed",
groupId));
+ }
+// long startTime = System.currentTimeMillis();
+// while (!createResult) {
+// createResult = checkConsumerGroupExist(mqAdminExt, groupId);
+// if (System.currentTimeMillis() - startTime < waitTimeSec * 1000)
{
+// TestUtils.waitForMoment(100);
+// } else {
+// log.error(String.format("timeout,but create consumeGroup[%s]
failed!", groupId));
+// break;
+// }
+// }
+// if (createResult) {
+// log.info("create consumeGroup:{} success", groupId);
+// }
+ return createResult;
+ }
+
+ private static boolean checkTopicExist(DefaultMQAdminExt mqAdminExt,
String topic) {
+ boolean createResult = false;
+ try {
+ TopicStatsTable topicInfo = mqAdminExt.examineTopicStats(topic);
+ createResult = !topicInfo.getOffsetTable().isEmpty();
+ } catch (Exception e) {
+ }
+ return createResult;
+ }
+
+ public static Boolean resetOffsetByTimestamp(String consumerGroup, String
topic, long timestamp) {
+ boolean result = false;
+ try {
+ mqAdminExt.resetOffsetByTimestamp(topic, consumerGroup, timestamp,
true);
+ result = true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ private static boolean checkConsumerGroupExist(DefaultMQAdminExt
mqAdminExt, String consumerGroup) {
+ boolean createResult = false;
+ try {
+ ConsumeStats consumeStats =
mqAdminExt.examineConsumeStats(consumerGroup);
+ createResult = !consumeStats.getOffsetTable().isEmpty();
+ } catch (Exception e) {
+ }
+ return createResult;
+ }
+
+ public static boolean createSub(String nameSrvAddr, String clusterName,
String consumerId) {
+ boolean createResult = true;
+ SubscriptionGroupConfig config = new SubscriptionGroupConfig();
+ config.setGroupName(consumerId);
+ try {
+ Set<String> masterSet =
CommandUtil.fetchMasterAddrByClusterName(mqAdminExt, clusterName);
+ for (String addr : masterSet) {
+ try {
+ mqAdminExt.createAndUpdateSubscriptionGroupConfig(addr,
config);
+ log.info(String.format("create subscription group %s to %s
success.\n", consumerId, addr));
+ } catch (Exception e) {
+ e.printStackTrace();
+ Thread.sleep(1000 * 1);
+ }
+ }
+ } catch (Exception e) {
+ createResult = false;
+ e.printStackTrace();
+ }
+ return createResult;
+ }
+
+ public static ClusterInfo getCluster(String nameSrvAddr) {
+ ClusterInfo clusterInfo = null;
+ try {
+ clusterInfo = mqAdminExt.examineBrokerClusterInfo();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return clusterInfo;
+ }
+
+ public static boolean isBrokerExist(String ns, String ip) {
+ ClusterInfo clusterInfo = getCluster(ns);
+ if (clusterInfo == null) {
+ return false;
+ } else {
+ Map<String, BrokerData> brokers = clusterInfo.getBrokerAddrTable();
+ for (Entry<String, BrokerData> brokerEntry : brokers.entrySet()) {
+ HashMap<Long, String> brokerIps =
brokerEntry.getValue().getBrokerAddrs();
+ for (Entry<Long, String> brokerIdEntry : brokerIps.entrySet())
{
+ if (brokerIdEntry.getValue().contains(ip)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static void deleteTopic(String nameSrvAddr, String cluster, String
topic) {
+ try {
+ Set<String> set = new HashSet<>();
+ set.add(nameSrvAddr);
+ mqAdminExt.deleteTopicInNameServer(set, topic);
+
+ boolean isTopicExist = checkTopicExist(mqAdminExt, topic);
+ long startTime = System.currentTimeMillis();
+ while (!isTopicExist) {
+ isTopicExist = checkTopicExist(mqAdminExt, topic);
+ if (System.currentTimeMillis() - startTime < 5 * 1000) {
+ TestUtils.waitForMoment(100);
+ } else {
+ log.error(String.format("timeout,but delete topic[%s]
failed!", topic));
+ break;
+ }
+ }
+
+ } catch (Exception e) {
+ }
+ }
+
+ public void getSubConnection(String nameSrvAddr, String clusterName,
String consumerId) {
+ SubscriptionGroupConfig config = new SubscriptionGroupConfig();
+ config.setGroupName(consumerId);
+ try {
+ Set<String> masterSet =
CommandUtil.fetchMasterAddrByClusterName(mqAdminExt, clusterName);
+ for (String addr : masterSet) {
+ try {
+
+ System.out.printf("create subscription group %s to %s
success.\n", consumerId, addr);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Thread.sleep(1000 * 1);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git
a/java/e2e-spring/src/main/java/org/apache/rocketmq/utils/RandomUtils.java
b/java/e2e-spring/src/main/java/org/apache/rocketmq/utils/RandomUtils.java
new file mode 100644
index 0000000..a5e2ef2
--- /dev/null
+++ b/java/e2e-spring/src/main/java/org/apache/rocketmq/utils/RandomUtils.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.utils;
+
+import java.util.Random;
+import java.util.UUID;
+
+public class RandomUtils {
+ private static final int UNICODE_START = '\u4E00';
+ private static final int UNICODE_END = '\u9FA0';
+ private static Random rd = new Random();
+
+ private RandomUtils() {
+
+ }
+
+ public static String getStringByUUID() {
+ return UUID.randomUUID().toString();
+ }
+
+ public static String getChineseWord(int len) {
+ StringBuilder res = new StringBuilder();
+
+ for (int i = 0; i < len; ++i) {
+ char str = getChineseChar();
+ res.append(str);
+ }
+
+ return res.toString();
+ }
+
+ public static String getStringWithNumber(int n) {
+ int[] arg = new int[] {'0', '9' + 1};
+ return getString(n, arg);
+ }
+
+ public static String getStringWithCharacter(int n) {
+ int[] arg = new int[] {'a', 'z' + 1, 'A', 'Z' + 1};
+ return getString(n, arg);
+ }
+
+ private static String getString(int n, int[] arg) {
+ StringBuilder res = new StringBuilder();
+ for (int i = 0; i < n; i++) {
+ res.append(getChar(arg));
+ }
+ return res.toString();
+ }
+
+ private static char getChar(int[] arg) {
+ int size = arg.length;
+ int c = rd.nextInt(size / 2);
+ c = c * 2;
+ return (char) (getIntegerBetween(arg[c], arg[c + 1]));
+ }
+
+ public static int getIntegerBetween(int n, int m) {
+ if (m == n) {
+ return n;
+ }
+ int res = getIntegerMoreThanZero();
+ return n + res % (m - n);
+ }
+
+ public static int getIntegerMoreThanZero() {
+ int res = rd.nextInt();
+ while (res <= 0) {
+ res = rd.nextInt();
+ }
+ return res;
+ }
+
+ private static char getChineseChar() {
+ return (char) (UNICODE_START + rd.nextInt(UNICODE_END -
UNICODE_START));
+ }
+}
diff --git
a/java/e2e-spring/src/main/java/org/apache/rocketmq/utils/TestUtils.java
b/java/e2e-spring/src/main/java/org/apache/rocketmq/utils/TestUtils.java
new file mode 100644
index 0000000..56efa3a
--- /dev/null
+++ b/java/e2e-spring/src/main/java/org/apache/rocketmq/utils/TestUtils.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+public class TestUtils {
+ private static final Logger log = LoggerFactory.getLogger(TestUtils.class);
+
+ private TestUtils() {
+ }
+
+ public static Long parseStringToLong(String s, Long defval) {
+ Long val;
+ try {
+ val = Long.parseLong(s);
+ } catch (NumberFormatException var4) {
+ val = defval;
+ }
+
+ return val;
+ }
+
+ public static Integer parseStringToInteger(String s, Integer defval) {
+ Integer val;
+ try {
+ val = Integer.parseInt(s);
+ } catch (NumberFormatException var4) {
+ val = defval;
+ }
+
+ return val;
+ }
+
+ public static String addQuoteToParamater(String param) {
+ StringBuilder sb = new StringBuilder("'");
+ sb.append(param).append("'");
+ return sb.toString();
+ }
+
+ public static void waitForMoment(long time) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException var3) {
+ var3.printStackTrace();
+ }
+
+ }
+
+ public static void waitForSeconds(long time) {
+ try {
+ log.info("waiting {} seconds...", time);
+ TimeUnit.SECONDS.sleep(time);
+ } catch (InterruptedException var3) {
+ var3.printStackTrace();
+ }
+
+ }
+
+ public static void waitForMinutes(long time) {
+ try {
+ log.info("waiting {} minutes...", time);
+ TimeUnit.MINUTES.sleep(time);
+ } catch (InterruptedException var3) {
+ var3.printStackTrace();
+ }
+
+ }
+
+ public static void waitForInputQuit() {
+ waitForInput("quit");
+ }
+
+ public static void waitForInput(String keyWord) {
+ waitForInput(keyWord, String.format("The thread will wait until you
input stop command[%s]:", keyWord));
+ }
+
+ public static void waitForInput(String keyWord, String info) {
+ try {
+ byte[] b = new byte[1024];
+ int n = System.in.read(b);
+
+ for (String s = (new String(b, 0, n - 1)).replace("\r",
"").replace("\n", ""); !s.equals(keyWord); s = new String(b, 0, n - 1)) {
+ n = System.in.read(b);
+ }
+ } catch (IOException var5) {
+ var5.printStackTrace();
+ }
+
+ }
+
+ public static <K, V extends Comparable<? super V>> Map<K, V>
sortByValue(Map<K, V> map) {
+ List<Map.Entry<K, V>> list = new LinkedList(map.entrySet());
+ Collections.sort(list, new Comparator<Map.Entry<K, V>>() {
+ @Override
+ public int compare(Map.Entry<K, V> o1, Map.Entry<K, V> o2) {
+ return ((Comparable) o1.getValue()).compareTo(o2.getValue());
+ }
+ });
+ Map<K, V> result = new LinkedHashMap();
+ Iterator var3 = list.iterator();
+
+ while (var3.hasNext()) {
+ Map.Entry<K, V> entry = (Map.Entry) var3.next();
+ result.put(entry.getKey(), entry.getValue());
+ }
+
+ return result;
+ }
+
+}
diff --git a/java/e2e-spring/src/main/resources/application.properties
b/java/e2e-spring/src/main/resources/application.properties
new file mode 100644
index 0000000..e9fbab9
--- /dev/null
+++ b/java/e2e-spring/src/main/resources/application.properties
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+spring.application.name=rocketmq-spring-e2e-test
+
+rocketmq.name-server=127.0.0.1:9876
+rocketmq.producer.group=my-group
+rocketmq.cluster=DefaultCluster
+# When set rocketmq.pull-consumer.group and rocketmq.pull-consumer.topic,
rocketmqTemplate will start lite pull consumer
+# If you do not want to use lite pull consumer, please do not set
rocketmq.pull-consumer.group and rocketmq.pull-consumer.topic
+#rocketmq.pull-consumer.group=my-group1
+#rocketmq.pull-consumer.topic=test
+# another nameserver different global
+rocketmq.test.topic.normal=topic-normal-spring-test
+rocketmq.test.topic.order=topic-order-spring-test
+rocketmq.test.topic.delay=topic-delay-spring-test
+rocketmq.test.topic.trans=topic-trans-spring-test
+rocketmq.pull-consumer.tlsEnable=false
+# ext rocketmq consumer template TLS
+#demo.ext.consumer.tlsEnable=false
diff --git
a/java/e2e-spring/src/test/java/org/apache/rocketmq/SpringBootBaseTest.java
b/java/e2e-spring/src/test/java/org/apache/rocketmq/SpringBootBaseTest.java
new file mode 100644
index 0000000..c27b77a
--- /dev/null
+++ b/java/e2e-spring/src/test/java/org/apache/rocketmq/SpringBootBaseTest.java
@@ -0,0 +1,32 @@
+package org.apache.rocketmq;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.utils.MQAdmin;
+import org.apache.rocketmq.utils.RandomUtils;
+import org.junit.jupiter.api.Assertions;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+
+
+@Slf4j
+@SpringBootTest(classes = RocketMQApplication.class)
+public class SpringBootBaseTest {
+ protected static String ALL_IP;
+ @Value("${rocketmq.cluster}")
+ private String cluster;
+
+ protected String getTopic(String messageType, String methodName) {
+ String topic = String.format("topic_%s_%s_%s", messageType,
methodName, RandomUtils.getStringWithCharacter(6));
+ log.info("[Topic] topic:{}, messageType:{}, methodName:{}", topic,
messageType, methodName);
+ boolean result = MQAdmin.createTopic(cluster, topic, 8, messageType);
+ Assertions.assertTrue(result, String.format("Create topic:%s failed",
topic));
+ return topic;
+ }
+
+ protected String getGroupId(String methodName) {
+ String groupId = String.format("GID_%s_%s", methodName,
RandomUtils.getStringWithCharacter(6));
+ log.info("[ConsumerGroupId] groupId:{}, methodName:{}", groupId,
methodName);
+ return groupId;
+ }
+
+}
diff --git
a/java/e2e-spring/src/test/java/org/apache/rocketmq/message/DelayMessageTest.java
b/java/e2e-spring/src/test/java/org/apache/rocketmq/message/DelayMessageTest.java
new file mode 100644
index 0000000..3f67718
--- /dev/null
+++
b/java/e2e-spring/src/test/java/org/apache/rocketmq/message/DelayMessageTest.java
@@ -0,0 +1,94 @@
+package org.apache.rocketmq.message;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.SpringBootBaseTest;
+import org.apache.rocketmq.client.DelayListenerImpl;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.client.producer.SendStatus;
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.concurrent.Callable;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.awaitility.Awaitility.await;
+
+@Slf4j
+public class DelayMessageTest extends SpringBootBaseTest {
+
+ @Autowired
+ private RocketMQTemplate rocketMQTemplate;
+ @Autowired
+ private DelayListenerImpl listener;
+ @Value("${rocketmq.test.topic.delay}")
+ private String delayTopic;
+
+ @Test
+ public void testDelayMessage() {
+ int delaySeconds = 10;
+ String message = "Hello, RocketMQ!";
+ SendResult sendResult =
rocketMQTemplate.syncSendDelayTimeMills(delayTopic, message, delaySeconds *
1000);
+ log.info("Send delay message: " + sendResult.getMsgId());
+ Assertions.assertEquals(sendResult.getSendStatus(),
SendStatus.SEND_OK);
+
+ Long sendTime = System.currentTimeMillis();
+ await().atMost(20, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ boolean result = false;
+ if
(listener.getReceivedMessageIds().contains(sendResult.getMsgId())) {
+ Long receivedTime =
listener.getReceivedMessages().get(sendResult.getMsgId());
+ if (Math.abs((receivedTime - sendTime) / 1000) -
delaySeconds < 5) {
+ result = true;
+ } else {
+ log.warn("Inaccurate delay time");
+ }
+ }
+ return result;
+ }
+ });
+ }
+
+ @Test
+ public void testDeliverTimeMessage() {
+ int delaySeconds = 10;
+ String message = "Hello, RocketMQ!";
+ SendResult sendResult =
rocketMQTemplate.syncSendDeliverTimeMills(delayTopic, message,
System.currentTimeMillis() + delaySeconds * 1000);
+ log.info("Send deliverTime message: " + sendResult.getMsgId());
+ Assertions.assertEquals(sendResult.getSendStatus(),
SendStatus.SEND_OK);
+
+ Long sendTime = System.currentTimeMillis();
+ await().atMost(20, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ boolean result = false;
+ if
(listener.getReceivedMessageIds().contains(sendResult.getMsgId())) {
+ Long receivedTime =
listener.getReceivedMessages().get(sendResult.getMsgId());
+ if (Math.abs((receivedTime - sendTime) / 1000) -
delaySeconds < 5) {
+ result = true;
+ } else {
+ log.warn("Inaccurate delay time");
+ }
+ }
+ return result;
+ }
+ });
+ }
+
+
+ @Data
+ @AllArgsConstructor
+ public class OrderPaidEvent implements Serializable {
+ private String orderId;
+
+ private BigDecimal paidMoney;
+ }
+
+}
diff --git
a/java/e2e-spring/src/test/java/org/apache/rocketmq/message/NormalMessageTest.java
b/java/e2e-spring/src/test/java/org/apache/rocketmq/message/NormalMessageTest.java
new file mode 100644
index 0000000..de661d5
--- /dev/null
+++
b/java/e2e-spring/src/test/java/org/apache/rocketmq/message/NormalMessageTest.java
@@ -0,0 +1,101 @@
+package org.apache.rocketmq.message;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.SpringBootBaseTest;
+import org.apache.rocketmq.client.NormalListenerImpl;
+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.spring.core.RocketMQTemplate;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.messaging.support.MessageBuilder;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.concurrent.Callable;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.awaitility.Awaitility.await;
+
+@Slf4j
+public class NormalMessageTest extends SpringBootBaseTest {
+
+ @Autowired
+ private RocketMQTemplate rocketMQTemplate;
+ @Autowired
+ private NormalListenerImpl consumer;
+ @Value("${rocketmq.test.topic.normal}")
+ private String normalTopic;
+
+ @Test
+ public void testSendMessage() {
+ String message = "Hello, RocketMQ!";
+ SendResult sendResult = rocketMQTemplate.syncSend(normalTopic,
MessageBuilder.withPayload(message).build());
+ log.info(sendResult.getMsgId());
+ Assertions.assertNotNull(sendResult);
+ Assertions.assertEquals(sendResult.getSendStatus(),
SendStatus.SEND_OK);
+ await().atMost(10, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ return
consumer.getReceivedMessageIds().contains(sendResult.getMsgId());
+ }
+ });
+ }
+
+ @Test
+ public void testAsyncSendMessage() {
+ final String[] messageId = {""};
+ rocketMQTemplate.asyncSend(normalTopic, new OrderPaidEvent("T_001",
new BigDecimal("88.00")), new SendCallback() {
+ @Override
+ public void onSuccess(SendResult sendResult) {
+ log.info(sendResult.getMsgId());
+ messageId[0] = sendResult.getMsgId();
+ }
+
+ @Override
+ public void onException(Throwable throwable) {
+ log.warn(throwable.getMessage());
+ }
+ });
+ await().atMost(10, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ return consumer.getReceivedMessageIds().contains(messageId[0]);
+ }
+ });
+ }
+
+ @Test
+ public void testConvertAndSend() {
+ String message = "Hello, RocketMQ!";
+ rocketMQTemplate.convertAndSend(normalTopic, message);
+ }
+
+ @Test
+ public void testSendOrderly() {
+ SendResult sendResult = rocketMQTemplate.syncSendOrderly(normalTopic,
new OrderPaidEvent("T_001", new BigDecimal("88.00")), "test");
+ log.info(sendResult.getMsgId());
+ Assertions.assertEquals(sendResult.getSendStatus(),
SendStatus.SEND_OK);
+ await().atMost(10, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ return
consumer.getReceivedMessageIds().contains(sendResult.getMsgId());
+ }
+ });
+ }
+
+
+ @Data
+ @AllArgsConstructor
+ public class OrderPaidEvent implements Serializable {
+ private String orderId;
+
+ private BigDecimal paidMoney;
+ }
+
+}
diff --git
a/java/e2e-spring/src/test/java/org/apache/rocketmq/message/OrderMessageTest.java
b/java/e2e-spring/src/test/java/org/apache/rocketmq/message/OrderMessageTest.java
new file mode 100644
index 0000000..547eb45
--- /dev/null
+++
b/java/e2e-spring/src/test/java/org/apache/rocketmq/message/OrderMessageTest.java
@@ -0,0 +1,75 @@
+package org.apache.rocketmq.message;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.SpringBootBaseTest;
+import org.apache.rocketmq.client.NormalListenerImpl;
+import org.apache.rocketmq.client.OrderListenerImpl;
+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.common.message.MessageExt;
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.messaging.support.MessageBuilder;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.awaitility.Awaitility.await;
+
+@Slf4j
+public class OrderMessageTest extends SpringBootBaseTest {
+
+ @Autowired
+ private RocketMQTemplate rocketMQTemplate;
+ @Autowired
+ private OrderListenerImpl listener;
+ @Value("${rocketmq.test.topic.order}")
+ private String orderTopic;
+
+ @Test
+ public void testSendOrderly() {
+ int msgSize = 50;
+ for (int i = 0; i < msgSize; i++) {
+ String hash = String.valueOf(i % 5);
+ SendResult sendResult =
rocketMQTemplate.syncSendOrderly(orderTopic, i, hash);
+ log.info("Send msgId:{}, queue:{}, hash:{}",
sendResult.getMsgId(), sendResult.getMessageQueue(), hash);
+ Assertions.assertEquals(sendResult.getSendStatus(),
SendStatus.SEND_OK);
+ }
+ await().atMost(30, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ return checkOrderMessage(listener.getMessageGroups());
+ }
+ });
+ }
+
+ public static boolean checkOrderMessage(ConcurrentHashMap<String,
LinkedList<MessageExt>> receivedMessage) {
+ for (Map.Entry<String, LinkedList<MessageExt>> stringLinkedListEntry :
receivedMessage.entrySet()) {
+ StringBuilder sb = new StringBuilder(String.format("shardingKey
%s,message order: ", stringLinkedListEntry.getKey()));
+ int preNode = -1;
+ LinkedList<MessageExt> messages = stringLinkedListEntry.getValue();
+ for (MessageExt message : messages) {
+ int curNode = Integer.parseInt(new String(message.getBody()));
+ sb.append(curNode).append(",");
+ if (preNode > curNode) {
+ log.error(sb.toString());
+ return false;
+ }
+ preNode = curNode;
+ }
+ }
+ return true;
+ }
+}
diff --git
a/java/e2e-spring/src/test/java/org/apache/rocketmq/message/TransMessageTest.java
b/java/e2e-spring/src/test/java/org/apache/rocketmq/message/TransMessageTest.java
new file mode 100644
index 0000000..fd80d51
--- /dev/null
+++
b/java/e2e-spring/src/test/java/org/apache/rocketmq/message/TransMessageTest.java
@@ -0,0 +1,113 @@
+package org.apache.rocketmq.message;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.rocketmq.SpringBootBaseTest;
+import org.apache.rocketmq.client.NormalListenerImpl;
+import org.apache.rocketmq.client.TransactionListenerImpl;
+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.spring.core.RocketMQLocalTransactionState;
+import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.awaitility.core.ConditionTimeoutException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.messaging.support.MessageBuilder;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.Duration;
+import java.util.concurrent.Callable;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@Slf4j
+public class TransMessageTest extends SpringBootBaseTest {
+
+ @Autowired
+ private RocketMQTemplate rocketMQTemplate;
+ @Autowired
+ private NormalListenerImpl consumer;
+ @Autowired
+ private TransactionListenerImpl transactionListener;
+ @Value("${rocketmq.test.topic.normal}")
+ private String normalTopic;
+
+ @Test
+ public void testTransExecuteCommitMessage() {
+ String message = "Hello, RocketMQ!";
+
transactionListener.setExecuteState(RocketMQLocalTransactionState.COMMIT);
+ SendResult sendResult =
rocketMQTemplate.sendMessageInTransaction(normalTopic,
MessageBuilder.withPayload(message).build(), null);
+ log.info(sendResult.getMsgId());
+ Assertions.assertEquals(sendResult.getSendStatus(),
SendStatus.SEND_OK);
+ Assertions.assertNotNull(sendResult.getTransactionId());
+ await().atMost(10, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ return
consumer.getReceivedMessageIds().contains(sendResult.getMsgId());
+ }
+ });
+ }
+
+ @Test
+ public void testTransExecuteRollbackMessage() {
+ String message = "Hello, RocketMQ!";
+
transactionListener.setExecuteState(RocketMQLocalTransactionState.ROLLBACK);
+ SendResult sendResult =
rocketMQTemplate.sendMessageInTransaction(normalTopic,
MessageBuilder.withPayload(message).build(), null);
+ log.info(sendResult.getMsgId());
+ Assertions.assertEquals(sendResult.getSendStatus(),
SendStatus.SEND_OK);
+ Assertions.assertNotNull(sendResult.getTransactionId());
+
+ assertThrows(ConditionTimeoutException.class, () -> {
+ await().atLeast(10, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ return
consumer.getReceivedMessageIds().contains(sendResult.getMsgId());
+ }
+ });
+ }, "Expected ConditionTimeoutException to throw, but it didn't");
+ }
+
+ @Test
+ public void testTransExecuteUnknowAndCheckCOMMITMessage() {
+ String message = "Hello, RocketMQ!";
+
transactionListener.setExecuteState(RocketMQLocalTransactionState.UNKNOWN);
+
transactionListener.setCheckState(RocketMQLocalTransactionState.COMMIT);
+ SendResult sendResult =
rocketMQTemplate.sendMessageInTransaction(normalTopic,
MessageBuilder.withPayload(message).build(), null);
+ log.info(sendResult.getMsgId());
+ Assertions.assertEquals(sendResult.getSendStatus(),
SendStatus.SEND_OK);
+ Assertions.assertNotNull(sendResult.getTransactionId());
+ await().atMost(30, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ return
consumer.getReceivedMessageIds().contains(sendResult.getMsgId());
+ }
+ });
+ }
+
+ @Test
+ public void testTransExecuteUnknowAndCheckRollbackMessage() {
+ String message = "Hello, RocketMQ!";
+
transactionListener.setExecuteState(RocketMQLocalTransactionState.UNKNOWN);
+
transactionListener.setCheckState(RocketMQLocalTransactionState.ROLLBACK);
+ SendResult sendResult =
rocketMQTemplate.sendMessageInTransaction(normalTopic,
MessageBuilder.withPayload(message).build(), null);
+ log.info(sendResult.getMsgId());
+ Assertions.assertEquals(sendResult.getSendStatus(),
SendStatus.SEND_OK);
+ Assertions.assertNotNull(sendResult.getTransactionId());
+
+ assertThrows(ConditionTimeoutException.class, () -> {
+ await().atLeast(10, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() {
+ return
consumer.getReceivedMessageIds().contains(sendResult.getMsgId());
+ }
+ });
+ }, "Expected ConditionTimeoutException to throw, but it didn't");
+ }
+}
diff --git a/java/e2e-spring/src/test/resources/junit-platform.properties
b/java/e2e-spring/src/test/resources/junit-platform.properties
new file mode 100644
index 0000000..97d8151
--- /dev/null
+++ b/java/e2e-spring/src/test/resources/junit-platform.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+junit.jupiter.execution.parallel.enabled=true
+junit.jupiter.execution.parallel.mode.default=concurrent
+junit.jupiter.execution.parallel.mode.classes.default=concurrent
+junit.jupiter.execution.parallel.config.dynamic.factor=1
\ No newline at end of file
diff --git a/java/e2e-spring/src/test/resources/log4j.properties
b/java/e2e-spring/src/test/resources/log4j.properties
new file mode 100644
index 0000000..1398339
--- /dev/null
+++ b/java/e2e-spring/src/test/resources/log4j.properties
@@ -0,0 +1,25 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+log4j.rootLogger=INFO, stdout
+#log4j.appender.ServerDailyRollingFile=org.apache.log4j.DailyRollingFileAppender
+#log4j.appender.ServerDailyRollingFile.DatePattern='.'yyyy-MM-dd
+##log4j.appender.ServerDailyRollingFile.File=${log.base}/logs/mq-server-test.log
+#log4j.appender.ServerDailyRollingFile.layout=org.apache.log4j.PatternLayout
+#log4j.appender.ServerDailyRollingFile.layout.ConversionPattern=%d - %m%n
+#log4j.appender.ServerDailyRollingFile.Append=true
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} %p
[%c.%M:%L] %m%n
\ No newline at end of file
diff --git a/java/e2e-spring/src/test/resources/logback-test.xml
b/java/e2e-spring/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..ce2a862
--- /dev/null
+++ b/java/e2e-spring/src/test/resources/logback-test.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<configuration debug="false" scan="true" scanPeriod="1 seconds">
+
+ <contextName>logback</contextName>
+ <!-- 输出到控制台 -->
+ <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <!--<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level
[%logger{12}#%M:%L] - %msg%n</pattern>-->
+ <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level
[%-30.30logger{12}#%-20.20M:%4L] %msg%n</pattern>
+ <charset>UTF-8</charset>
+ </encoder>
+ </appender>
+
+ <root level="debug">
+ <appender-ref ref="CONSOLE" />
+ </root>
+
+</configuration>
\ No newline at end of file
diff --git a/java/e2e-v4/pom.xml b/java/e2e-v4/pom.xml
index 5ae3c84..13874d2 100644
--- a/java/e2e-v4/pom.xml
+++ b/java/e2e-v4/pom.xml
@@ -12,10 +12,8 @@
<artifactId>rocketmq-java-e2e-v4</artifactId>
<properties>
- <maven.compiler.source>8</maven.compiler.source>
- <maven.compiler.target>8</maven.compiler.target>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<rocketmq.client.version>4.9.3</rocketmq.client.version>
+ <junit.jupiter.version>5.7.2</junit.jupiter.version>
</properties>
<dependencies>
@@ -36,6 +34,44 @@
<artifactId>rocketmq-tools</artifactId>
<version>${rocketmq.client.version}</version>
</dependency>
+
+ <!--junit5-->
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-launcher</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <version>${junit.jupiter.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <version>${junit.jupiter.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
+ <version>${junit.jupiter.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>2.0.0-beta1</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.3.0-beta0</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>1.3.0-beta0</version>
+ </dependency>
</dependencies>
<build>
diff --git
a/java/e2e-v4/src/test/java/com/apache/rocketmq/server/delay/DelayMessageTest.java
b/java/e2e-v4/src/test/java/org/apache/rocketmq/server/delay/DelayMessageTest.java
similarity index 98%
rename from
java/e2e-v4/src/test/java/com/apache/rocketmq/server/delay/DelayMessageTest.java
rename to
java/e2e-v4/src/test/java/org/apache/rocketmq/server/delay/DelayMessageTest.java
index 7d8515c..90b1b11 100644
---
a/java/e2e-v4/src/test/java/com/apache/rocketmq/server/delay/DelayMessageTest.java
+++
b/java/e2e-v4/src/test/java/org/apache/rocketmq/server/delay/DelayMessageTest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.apache.rocketmq.server.delay;
+package org.apache.rocketmq.server.delay;
import org.apache.rocketmq.client.rmq.RMQNormalConsumer;
import org.apache.rocketmq.client.rmq.RMQNormalProducer;
diff --git
a/java/e2e-v4/src/test/java/com/apache/rocketmq/server/normal/NormalMessageTest.java
b/java/e2e-v4/src/test/java/org/apache/rocketmq/server/normal/NormalMessageTest.java
similarity index 99%
rename from
java/e2e-v4/src/test/java/com/apache/rocketmq/server/normal/NormalMessageTest.java
rename to
java/e2e-v4/src/test/java/org/apache/rocketmq/server/normal/NormalMessageTest.java
index 9393bde..7506da4 100644
---
a/java/e2e-v4/src/test/java/com/apache/rocketmq/server/normal/NormalMessageTest.java
+++
b/java/e2e-v4/src/test/java/org/apache/rocketmq/server/normal/NormalMessageTest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.apache.rocketmq.server.normal;
+package org.apache.rocketmq.server.normal;
import org.apache.rocketmq.client.callback.RMQSendCallBack;
import org.apache.rocketmq.client.rmq.RMQNormalConsumer;
diff --git
a/java/e2e-v4/src/test/java/com/apache/rocketmq/server/order/OrderMessageTest.java
b/java/e2e-v4/src/test/java/org/apache/rocketmq/server/order/OrderMessageTest.java
similarity index 98%
rename from
java/e2e-v4/src/test/java/com/apache/rocketmq/server/order/OrderMessageTest.java
rename to
java/e2e-v4/src/test/java/org/apache/rocketmq/server/order/OrderMessageTest.java
index 9e7bb1c..26092fa 100644
---
a/java/e2e-v4/src/test/java/com/apache/rocketmq/server/order/OrderMessageTest.java
+++
b/java/e2e-v4/src/test/java/org/apache/rocketmq/server/order/OrderMessageTest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.apache.rocketmq.server.order;
+package org.apache.rocketmq.server.order;
import org.apache.rocketmq.client.rmq.RMQNormalConsumer;
import org.apache.rocketmq.client.rmq.RMQNormalProducer;
diff --git
a/java/e2e-v4/src/test/java/com/apache/rocketmq/server/transaction/TransactionMessageTest.java
b/java/e2e-v4/src/test/java/org/apache/rocketmq/server/transaction/TransactionMessageTest.java
similarity index 98%
rename from
java/e2e-v4/src/test/java/com/apache/rocketmq/server/transaction/TransactionMessageTest.java
rename to
java/e2e-v4/src/test/java/org/apache/rocketmq/server/transaction/TransactionMessageTest.java
index 5721154..ced5929 100644
---
a/java/e2e-v4/src/test/java/com/apache/rocketmq/server/transaction/TransactionMessageTest.java
+++
b/java/e2e-v4/src/test/java/org/apache/rocketmq/server/transaction/TransactionMessageTest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package com.apache.rocketmq.server.transaction;
+package org.apache.rocketmq.server.transaction;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.rmq.RMQNormalConsumer;
diff --git a/java/e2e/pom.xml b/java/e2e/pom.xml
index 7a211cb..76ba5bf 100644
--- a/java/e2e/pom.xml
+++ b/java/e2e/pom.xml
@@ -16,6 +16,7 @@
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<rocketmqV5.client.version>5.0.3</rocketmqV5.client.version>
+ <junit.jupiter.version>5.7.2</junit.jupiter.version>
</properties>
<dependencies>
@@ -50,6 +51,44 @@
<artifactId>awaitility</artifactId>
<version>4.0.3</version>
</dependency>
+
+ <!--junit5-->
+ <dependency>
+ <groupId>org.junit.platform</groupId>
+ <artifactId>junit-platform-launcher</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <version>${junit.jupiter.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <version>${junit.jupiter.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
+ <version>${junit.jupiter.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>2.0.0-beta1</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.3.0-beta0</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>1.3.0-beta0</version>
+ </dependency>
</dependencies>
<build>
diff --git a/java/pom.xml b/java/pom.xml
index 444f170..76ca102 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -11,59 +11,128 @@
<modules>
<module>e2e</module>
<module>e2e-v4</module>
+ <module>e2e-spring</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <junit.jupiter.version>5.7.2</junit.jupiter.version>
+
+ <jdk.version>8</jdk.version>
</properties>
<dependencies>
- <!--junit5-->
- <dependency>
- <groupId>org.junit.platform</groupId>
- <artifactId>junit-platform-launcher</artifactId>
- <version>1.7.2</version>
- </dependency>
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-api</artifactId>
- <version>${junit.jupiter.version}</version>
- </dependency>
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-engine</artifactId>
- <version>${junit.jupiter.version}</version>
- </dependency>
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-params</artifactId>
- <version>${junit.jupiter.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- <version>2.0.0-beta1</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- <version>1.3.0-beta0</version>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-core</artifactId>
- <version>1.3.0-beta0</version>
- </dependency>
-
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
</dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>2.17</version>
+ <executions>
+ <execution>
+ <id>verify</id>
+ <phase>verify</phase>
+ <configuration>
+
<configLocation>style/rmq_checkstyle.xml</configLocation>
+ <encoding>UTF-8</encoding>
+ <consoleOutput>true</consoleOutput>
+ <failsOnError>true</failsOnError>
+
<includeTestSourceDirectory>false</includeTestSourceDirectory>
+ </configuration>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ <version>0.12</version>
+ <configuration>
+ <excludes>
+ <exclude>.gitignore</exclude>
+ <exclude>.travis.yml</exclude>
+ <exclude>CONTRIBUTING.md</exclude>
+ <exclude>bin/README.md</exclude>
+ <exclude>.github/**</exclude>
+ <exclude>src/test/resources/certs/*</exclude>
+ <exclude>src/test/**/*.log</exclude>
+
<exclude>src/test/resources/META-INF/service/*</exclude>
+
<exclude>src/main/resources/META-INF/service/*</exclude>
+ <exclude>*/target/**</exclude>
+ <exclude>*/*.iml</exclude>
+ <exclude>docs/**</exclude>
+ <exclude>localbin/**</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-eclipse-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>3.0.0-M5</version>
+ <configuration>
+ <argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
+ <!--
<rerunFailingTestsCount>1</rerunFailingTestsCount>-->
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <version>2.22.2</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.0</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.8</version>
+ <executions>
+ <execution>
+ <id>add-test-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+
<source>${project.basedir}/src/test/java</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>**/*.conf</include>
+ <include>**/*.properties</include>
+ </includes>
+ </resource>
+ </resources>
+ </build>
</project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 1023fd7..4d7bd55 100644
--- a/pom.xml
+++ b/pom.xml
@@ -109,6 +109,7 @@
<build>
<plugins>
<plugin>
+ <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.17</version>
<executions>