diff --git a/esua-epdc/epdc-admin/epdc-admin-server/pom.xml b/esua-epdc/epdc-admin/epdc-admin-server/pom.xml index 78a99d64f..e46f27bb6 100644 --- a/esua-epdc/epdc-admin/epdc-admin-server/pom.xml +++ b/esua-epdc/epdc-admin/epdc-admin-server/pom.xml @@ -62,6 +62,12 @@ feign-httpclient 10.3.0 + + + org.apache.rocketmq + rocketmq-spring-boot-starter + 2.0.3 + @@ -141,6 +147,9 @@ wx9b6102a8ee5add65 394f47d4e08fc0fd629231d3f68a34dc + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup @@ -167,6 +176,9 @@ wx9b6102a8ee5add65 394f47d4e08fc0fd629231d3f68a34dc + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup diff --git a/esua-epdc/epdc-admin/epdc-admin-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java b/esua-epdc/epdc-admin/epdc-admin-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java new file mode 100644 index 000000000..d6b508709 --- /dev/null +++ b/esua-epdc/epdc-admin/epdc-admin-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java @@ -0,0 +1,37 @@ +package com.elink.esua.epdc.rocketmq.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * + * 组织机构信息修改-发送MQ消息DTO + * + * @Author:liuchuang + * @Date:2020/3/6 19:58 + */ +@Data +public class OrganizationModifyDTO implements Serializable { + private static final long serialVersionUID = -1330090682508121169L; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 旧部门名称 + */ + private String oldDeptName; + + /** + * 新部门名称 + */ + private String newDeptName; + + /** + * 部门类型 + */ + private String typeKey; +} diff --git a/esua-epdc/epdc-admin/epdc-admin-server/src/main/java/com/elink/esua/epdc/rocketmq/producer/OrganizationModifyProducer.java b/esua-epdc/epdc-admin/epdc-admin-server/src/main/java/com/elink/esua/epdc/rocketmq/producer/OrganizationModifyProducer.java new file mode 100644 index 000000000..48cc8b0bb --- /dev/null +++ b/esua-epdc/epdc-admin/epdc-admin-server/src/main/java/com/elink/esua/epdc/rocketmq/producer/OrganizationModifyProducer.java @@ -0,0 +1,44 @@ +package com.elink.esua.epdc.rocketmq.producer; + +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * 组织机构信息修改-发送MQ消息 + * + * @Author:liuchuang + * @Date:2020/3/5 17:53 + */ +@Slf4j +@Component +public class OrganizationModifyProducer { + + @Autowired + private RocketMQTemplate rocketMQTemplate; + + /** + * + * 发送消息 + * + * @params [topic, tag, keys, body] + * @return void + * @author liuchuang + * @since 2020/3/6 21:09 + */ + public void sendMessage(String topic, String tag, String keys, String body) { + Message message = new Message(topic, tag, keys, body.getBytes()); + try { + SendResult sendResult = rocketMQTemplate.getProducer().send(message); + log.info("EPDC-ADMIN-SERVER发送消息结果:{sendStatus:{}, topic:{}, msgId:{}}", sendResult.getSendStatus(), topic, sendResult.getMsgId()); + } catch (Exception e) { + log.error("EPDC-ADMIN-SERVER发送消息异常:{topic:{}, tag:{}, keys:{}, body:{}}", topic, tag, keys, body); + e.printStackTrace(); + } + } + +} diff --git a/esua-epdc/epdc-admin/epdc-admin-server/src/main/java/com/elink/esua/epdc/service/impl/SysDeptServiceImpl.java b/esua-epdc/epdc-admin/epdc-admin-server/src/main/java/com/elink/esua/epdc/service/impl/SysDeptServiceImpl.java index 110e343e7..4057c6d19 100644 --- a/esua-epdc/epdc-admin/epdc-admin-server/src/main/java/com/elink/esua/epdc/service/impl/SysDeptServiceImpl.java +++ b/esua-epdc/epdc-admin/epdc-admin-server/src/main/java/com/elink/esua/epdc/service/impl/SysDeptServiceImpl.java @@ -14,10 +14,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.elink.esua.epdc.commons.mybatis.service.impl.BaseServiceImpl; -import com.elink.esua.epdc.commons.tools.constant.Constant; -import com.elink.esua.epdc.commons.tools.constant.FieldConstant; -import com.elink.esua.epdc.commons.tools.constant.NumConstant; -import com.elink.esua.epdc.commons.tools.constant.OrganizationTypeConstant; +import com.elink.esua.epdc.commons.tools.constant.*; import com.elink.esua.epdc.commons.tools.enums.SuperAdminEnum; import com.elink.esua.epdc.commons.tools.exception.ErrorCode; import com.elink.esua.epdc.commons.tools.exception.RenException; @@ -37,6 +34,8 @@ import com.elink.esua.epdc.dto.epdc.form.UserSysDeptInfoFormDTO; import com.elink.esua.epdc.dto.epdc.result.UserSysDeptInfoResultDTO; import com.elink.esua.epdc.entity.SysDeptEntity; import com.elink.esua.epdc.feign.GroupFeignClient; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; +import com.elink.esua.epdc.rocketmq.producer.OrganizationModifyProducer; import com.elink.esua.epdc.service.SysDeptService; import com.elink.esua.epdc.service.SysUserService; import com.google.common.collect.Lists; @@ -75,6 +74,9 @@ public class SysDeptServiceImpl extends BaseServiceImpl userDtoList = this.baseDao.selectListCompleteDeptDTO(params); return new PageData<>(userDtoList, iPage.getTotal()); } + + /** + * + * 组织机构名称修改发送MQ消息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/6 21:34 + */ + private void sendMqMessage(SysDeptDTO dto) { + // 获取旧信息 + SysDeptEntity entity = baseDao.getById(dto.getId()); + if (!dto.getName().equals(entity.getName())) { + OrganizationModifyDTO body = new OrganizationModifyDTO(); + body.setDeptId(dto.getId()); + body.setOldDeptName(entity.getName()); + body.setNewDeptName(dto.getName()); + body.setTypeKey(entity.getTypeKey()); + organizationModifyProducer.sendMessage(RocketMqConstant.MQ_TOPIC_ORGANIZATION, RocketMqConstant.MQ_TAG_ORGANIZATION, + dto.getId().toString(), JSONObject.toJSONString(body)); + } + } } diff --git a/esua-epdc/epdc-admin/epdc-admin-server/src/main/resources/application.yml b/esua-epdc/epdc-admin/epdc-admin-server/src/main/resources/application.yml index ecd16eb5a..51e150c03 100644 --- a/esua-epdc/epdc-admin/epdc-admin-server/src/main/resources/application.yml +++ b/esua-epdc/epdc-admin/epdc-admin-server/src/main/resources/application.yml @@ -110,4 +110,10 @@ hystrix: ribbon: ReadTimeout: 300000 - ConnectTimeout: 300000 \ No newline at end of file + ConnectTimeout: 300000 + + +rocketmq: + name-server: @rocketmq.name.server@ + producer: + group: @rocketmq.producer.group@ \ No newline at end of file diff --git a/esua-epdc/epdc-commons/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/RocketMqConstant.java b/esua-epdc/epdc-commons/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/RocketMqConstant.java new file mode 100644 index 000000000..78a31f087 --- /dev/null +++ b/esua-epdc/epdc-commons/epdc-commons-tools/src/main/java/com/elink/esua/epdc/commons/tools/constant/RocketMqConstant.java @@ -0,0 +1,31 @@ +package com.elink.esua.epdc.commons.tools.constant; + +/** + * + * RocketMq 常量类 + * + * @Author:liuchuang + * @Date:2020/3/6 20:52 + */ +public interface RocketMqConstant { + + /** + * 组织机构信息修改-消息topic + */ + String MQ_TOPIC_ORGANIZATION = "organizationTopic"; + + /** + * 组织机构信息修改-消息tag + */ + String MQ_TAG_ORGANIZATION = "organizationTag"; + + /** + * 分类信息修改-消息topic + */ + String MQ_TOPIC_CATEGORY = "categoryTopic"; + + /** + * 分类信息修改-消息tag + */ + String MQ_TAG_CATEGORY = "categoryTag"; +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.github/ISSUE_TEMPLATE.md b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..6d6dcd296 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,25 @@ +The issue tracker is **ONLY** used for bug report and feature request. + +Any question or RocketMQ proposal please use our [mailing lists](http://rocketmq.apache.org/about/contact/). + +**BUG REPORT** + +1. Please describe the issue you observed: + +- What did you do (The steps to reproduce)? + +- What did you expect to see? + +- What did you see instead? + +2. Please tell us about your environment: + +3. Other information (e.g. detailed explanation, logs, related issues, suggestions how to fix, etc): + +**FEATURE REQUEST** + +1. Please describe the feature you are requesting. + +2. Provide any additional detail on your proposed use case for this feature. + +3. Indicate the importance of this issue to you (blocker, must-have, should-have, nice-to-have). Are you currently using any workarounds to address this issue? diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.github/PULL_REQUEST_TEMPLATE.md b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..5799172d9 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ +## What is the purpose of the change + +XXXXX + +## Brief changelog + +XX + +## Verifying this change + +XXXX + +Follow this checklist to help us incorporate your contribution quickly and easily. Notice, `it would be helpful if you could finish the following 5 checklist(the last one is not necessary)before request the community to review your PR`. + +- [x] Make sure there is a [Github issue](https://github.com/apache/rocketmq/issues) filed for the change (usually before you start working on it). Trivial changes like typos do not require a Github issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue. +- [x] Format the pull request title like `[ISSUE #123] Fix UnknownException when host config not exist`. Each commit in the pull request should have a meaningful subject line and body. +- [x] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. +- [x] Write necessary unit-test(over 80% coverage) to verify your logic correction, more mock a little better when cross module dependency exist. +- [x] Run `mvn -B clean apache-rat:check findbugs:findbugs checkstyle:checkstyle` to make sure basic checks pass. Run `mvn clean install -DskipITs` to make sure unit-test pass. Run `mvn clean test-compile failsafe:integration-test` to make sure integration-test pass. +- [ ] If this contribution is large, please file an [Apache Individual Contributor License Agreement](http://www.apache.org/licenses/#clas). diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.gitignore b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.gitignore new file mode 100644 index 000000000..06bb32640 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.gitignore @@ -0,0 +1,13 @@ +.idea +.classpath +.project +.settings/ +target/ +*.log* +*.iml +.idea/ +*.versionsBackup +!NOTICE-BIN +!LICENSE-BIN +.DS_Store +.vscode diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.travis.yml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.travis.yml new file mode 100644 index 000000000..24e6a65a2 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/.travis.yml @@ -0,0 +1,30 @@ +notifications: + email: + recipients: + - dev@rocketmq.apache.org + on_success: change + on_failure: always + +language: java + +matrix: + include: + # On OSX, run with default JDK only. + # - os: osx + # On Linux, run with specific JDKs only. + - os: linux + env: CUSTOM_JDK="oraclejdk8" + +before_install: + - echo 'MAVEN_OPTS="$MAVEN_OPTS -Xmx1024m -XX:MaxPermSize=512m -XX:+BytecodeVerificationLocal"' >> ~/.mavenrc + - cat ~/.mavenrc + - if [ "$TRAVIS_OS_NAME" == "osx" ]; then export JAVA_HOME=$(/usr/libexec/java_home); fi + - if [ "$TRAVIS_OS_NAME" == "linux" ]; then jdk_switcher use "$CUSTOM_JDK"; fi + +script: + - travis_retry mvn -B clean apache-rat:check + - travis_retry mvn -B package jacoco:report coveralls:report + +after_success: + # - mvn clean install -Pit-test + - mvn sonar:sonar -Psonar-apache diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/LICENSE b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/LICENSE new file mode 100644 index 000000000..7a4a3ea24 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/NOTICE b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/NOTICE new file mode 100644 index 000000000..f07078d7c --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/NOTICE @@ -0,0 +1,5 @@ +Apache RocketMQ +Copyright 2016-2018 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/README.md b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/README.md new file mode 100644 index 000000000..f8edadce2 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/README.md @@ -0,0 +1,406 @@ +# RocketMQ-Spring [![Build Status](https://travis-ci.org/apache/rocketmq-spring.svg?branch=master)](https://travis-ci.org/apache/rocketmq-spring) [![Coverage Status](https://coveralls.io/repos/github/apache/rocketmq-spring/badge.svg?branch=master)](https://coveralls.io/github/apache/rocketmq-spring?branch=master) + +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.rocketmq/rocketmq-spring-all/badge.svg)](https://search.maven.org/search?q=g:org.apache.rocketmq%20AND%20a:rocketmq-spring-all) +[![GitHub release](https://img.shields.io/badge/release-download-orange.svg)](https://github.com/apache/rocketmq-spring/releases) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) + +[中文](./README_zh_CN.md) + +## Introduction + +This project aims to help developers quickly integrate [RocketMQ](http://rocketmq.apache.org/) with [Spring Boot](http://projects.spring.io/spring-boot/). + +## How To Contribute + +We are always very happy to have contributions, whether for trivial cleanups or big new features. Please see the RocketMQ main website to read [details](http://rocketmq.apache.org/docs/how-to-contribute/) + + +## Prerequisites +- JDK 1.8 and above +- [Maven](http://maven.apache.org/) 3.0 and above + +## Build and Install with local maven repository + +``` + mvn clean install +``` + +## Features: + +- [x] synchronous transmission +- [x] synchronous ordered transmission +- [x] synchronous batch transmission +- [x] asynchronous transmission +- [x] asynchronous ordered transmission +- [x] orderly consume +- [x] concurrently consume(broadcasting/clustering) +- [x] one-way transmission +- [x] transaction transmission +- [x] message trace +- [x] ACL +- [ ] pull consume + +## Quick Start + +Please see the complete sample [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples) + +Note: Current RELEASE.VERSION=2.0.3 + +```xml + + + org.apache.rocketmq + rocketmq-spring-boot-starter + ${RELEASE.VERSION} + +``` + +### Produce Message + +```properties +## application.properties +rocketmq.name-server=127.0.0.1:9876 +rocketmq.producer.group=my-group +``` + +> Note: +> +> Maybe you need change `127.0.0.1:9876` with your real NameServer address for RocketMQ + +```java +@SpringBootApplication +public class ProducerApplication implements CommandLineRunner{ + @Resource + private RocketMQTemplate rocketMQTemplate; + + public static void main(String[] args){ + SpringApplication.run(ProducerApplication.class, args); + } + + public void run(String... args) throws Exception { + rocketMQTemplate.convertAndSend("test-topic-1", "Hello, World!"); + rocketMQTemplate.send("test-topic-1", MessageBuilder.withPayload("Hello, World! I'm from spring message").build()); + rocketMQTemplate.convertAndSend("test-topic-2", new OrderPaidEvent("T_001", new BigDecimal("88.00"))); + +// rocketMQTemplate.destroy(); // notes: once rocketMQTemplate be destroyed, you can not send any message again with this rocketMQTemplate + } + + @Data + @AllArgsConstructor + public class OrderPaidEvent implements Serializable{ + private String orderId; + + private BigDecimal paidMoney; + } +} +``` + +> More relevant configurations for producing: +> +> ```properties +> rocketmq.producer.send-message-timeout=300000 +> rocketmq.producer.compress-message-body-threshold=4096 +> rocketmq.producer.max-message-size=4194304 +> rocketmq.producer.retry-times-when-send-async-failed=0 +> rocketmq.producer.retry-next-server=true +> rocketmq.producer.retry-times-when-send-failed=2 +> ``` + + +### Send message in transaction and implement local check Listener +```java +@SpringBootApplication +public class ProducerApplication implements CommandLineRunner{ + @Resource + private RocketMQTemplate rocketMQTemplate; + + public static void main(String[] args){ + SpringApplication.run(ProducerApplication.class, args); + } + + public void run(String... args) throws Exception { + try { + // Build a SpringMessage for sending in transaction + Message msg = MessageBuilder.withPayload(..)...; + // In sendMessageInTransaction(), the first parameter transaction name ("test") + // must be same with the @RocketMQTransactionListener's member field 'transName' + rocketMQTemplate.sendMessageInTransaction("test", "test-topic", msg, null); + } catch (MQClientException e) { + e.printStackTrace(System.out); + } + } + + // Define transaction listener with the annotation @RocketMQTransactionListener + @RocketMQTransactionListener(transName="test") + class TransactionListenerImpl implements RocketMQLocalTransactionListener { + @Override + public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { + // ... local transaction process, return bollback, commit or unknown + return RocketMQLocalTransactionState.UNKNOWN; + } + + @Override + public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { + // ... check transaction status and return bollback, commit or unknown + return RocketMQLocalTransactionState.COMMIT; + } + } +} +``` + +### Consume Message + +```properties +## application.properties +rocketmq.name-server=127.0.0.1:9876 +``` + +> Note: +> +> Maybe you need change `127.0.0.1:9876` with your real NameServer address for RocketMQ + +```java +@SpringBootApplication +public class ConsumerApplication{ + + public static void main(String[] args){ + SpringApplication.run(ConsumerApplication.class, args); + } + + @Slf4j + @Service + @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1") + public class MyConsumer1 implements RocketMQListener{ + public void onMessage(String message) { + log.info("received message: {}", message); + } + } + + @Slf4j + @Service + @RocketMQMessageListener(topic = "test-topic-2", consumerGroup = "my-consumer_test-topic-2") + public class MyConsumer2 implements RocketMQListener{ + public void onMessage(OrderPaidEvent orderPaidEvent) { + log.info("received orderPaidEvent: {}", orderPaidEvent); + } + } +} +``` + +> More relevant configurations for consuming: +> +> see: [RocketMQMessageListener](rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQMessageListener.java) + +### Message Trace + +We need 2 more configurations for support message trace in producer. + +```properties +## application.properties +rocketmq.name-server=127.0.0.1:9876 +rocketmq.producer.group=my-group + +rocketmq.producer.enable-msg-trace=true +rocketmq.producer.customized-trace-topic=my-trace-topic +``` + +The message trace in consumer should configure in `@RocketMQMessageListener`. + +``` +@Service +@RocketMQMessageListener( + topic = "test-topic-1", + consumerGroup = "my-consumer_test-topic-1", + enableMsgTrace = true, + customizedTraceTopic = "my-trace-topic" +) +public class MyConsumer implements RocketMQListener { + ... +} +``` + + +> Note: +> +> Maybe you need change `127.0.0.1:9876` with your real NameServer address for RocketMQ + +> By default, the message track feature of Producer and Consumer is turned on and the trace-topic is RMQ_SYS_TRACE_TOPIC +> The topic of message trace can be configured with `rocketmq.consumer.customized-trace-topic` configuration item, not required to be configured in each `@RocketMQTransactionListener` + + +### ACL + +We need 2 more configurations for support ACL in producer. + +```properties +## application.properties +rocketmq.name-server=127.0.0.1:9876 +rocketmq.producer.group=my-group + +rocketmq.producer.access-key=AK +rocketmq.producer.secret-key=SK +``` +Transaction Message should configure AK/SK in `@RocketMQTransactionListener`. + +``` +@RocketMQTransactionListener( + txProducerGroup = "test, + accessKey = "AK", + secretKey = "SK" +) +class TransactionListenerImpl implements RocketMQLocalTransactionListener { + ... +} +``` + +> Note: +> +> You do not need to configure AK/SK for each `@RocketMQTransactionListener`, you could configure `rocketmq.producer.access-key` and `rocketmq.producer.secret-key` as default value + +The ACL feature in consumer should configure AK/SK in `@RocketMQMessageListener`. + +``` +@Service +@RocketMQMessageListener( + topic = "test-topic-1", + consumerGroup = "my-consumer_test-topic-1", + accessKey = "AK", + secretKey = "SK" +) +public class MyConsumer implements RocketMQListener { + ... +} +``` + +> Note: +> +> You do not need to configure AK/SK for each `@RocketMQMessageListener`, you could configure `rocketmq.consumer.access-key` and `rocketmq.consumer.secret-key` as default value + +## FAQ + +1. How to connected many `nameserver` on production environment? + + `rocketmq.name-server` support the configuration of multiple `nameserver`, separated by `;`. For example: `172.19.0.1: 9876; 172.19.0.2: 9876` + +1. When was `rocketMQTemplate` destroyed? + + Developers do not need to manually execute the `rocketMQTemplate.destroy ()` method when using `rocketMQTemplate` to send a message in the project, and` rocketMQTemplate` will be destroyed automatically when the spring container is destroyed. + +1. start exception:`Caused by: org.apache.rocketmq.client.exception.MQClientException: The consumer group[xxx] has been created before, specify another name please` + + RocketMQ in the design do not want a consumer to deal with multiple types of messages at the same time, so the same `consumerGroup` consumer responsibility should be the same, do not do different things (that is, consumption of multiple topics). Suggested `consumerGroup` and` topic` one correspondence. + +1. How is the message content body being serialized and deserialized? + + RocketMQ's message body is stored as `byte []`. When the business system message content body if it is `java.lang.String` type, unified in accordance with` utf-8` code into `byte []`; If the business system message content is not `java.lang.String` Type, then use [jackson-databind](https://github.com/FasterXML/jackson-databind) serialized into the `JSON` format string, and then unified in accordance with` utf-8` code into `byte [] `. + +1. How do I specify the `tags` for topic? + + RocketMQ best practice recommended: an application as much as possible with one Topic, the message sub-type with `tags` to identify,` tags` can be set by the application free. + + When you use `rocketMQTemplate` to send a message, set the destination of the message by setting the` destination` parameter of the send method. The `destination` format is `topicName:tagName`, `:` Precedes the name of the topic, followed by the `tags` name. + + > Note: + > + > `tags` looks a complex, but when sending a message , the destination can only specify one topic under a `tag`, can not specify multiple. + +1. How do I set the message's `key` when sending a message? + + You can send a message by overloading method like `xxxSend(String destination, Message msg, ...)`, setting `headers` of `msg`. for example: + + ```java + Message message = MessageBuilder.withPayload(payload).setHeader(MessageConst.PROPERTY_KEYS, msgId).build(); + rocketMQTemplate.send("topic-test", message); + ``` + + Similarly, you can also set the message `FLAG`,` WAIT_STORE_MSG_OK` and some other user-defined other header information according to the above method. + + > Note: + > + > In the case of converting Spring's Message to RocketMQ's Message, to prevent the `header` information from conflicting with RocketMQ's system properties, the prefix `USERS_` was added in front of all `header` names. So if you want to get a custom message header when consuming, please pass through the key at the beginning of `USERS_` in the header. + +1. When consume message, in addition to get the message `payload`, but also want to get RocketMQ message of other system attributes, how to do? + + Consumers in the realization of `RocketMQListener` interface, only need to be generic for the` MessageExt` can, so in the `onMessage` method will receive RocketMQ native 'MessageExt` message. + + ```java + @Slf4j + @Service + @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1") + public class MyConsumer2 implements RocketMQListener{ + public void onMessage(MessageExt messageExt) { + log.info("received messageExt: {}", messageExt); + } + } + ``` + +1. How do I specify where consumers start consuming messages? + + The default consume offset please refer: [RocketMQ FAQ](http://rocketmq.apache.org/docs/faq/). + To customize the consumer's starting location, simply add a `RocketMQPushConsumerLifecycleListener` interface implementation to the consumer class. Examples are as follows: + + ```java + @Slf4j + @Service + @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1") + public class MyConsumer1 implements RocketMQListener, RocketMQPushConsumerLifecycleListener { + @Override + public void onMessage(String message) { + log.info("received message: {}", message); + } + + @Override + public void prepareStart(final DefaultMQPushConsumer consumer) { + // set consumer consume message from now + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP); + consumer.setConsumeTimestamp(UtilAll.timeMillisToHumanString3(System.currentTimeMillis())); + } + } + ``` + + Similarly, any other configuration on `DefaultMQPushConsumer` can be done in the same way as above. + + +1. How do I send transactional messages? + It needs two steps on client side: + + a) Define a class which is annotated with @RocketMQTransactionListener and implements RocketMQLocalTransactionListener interface, in which, the executeLocalTransaction() and checkLocalTransaction() methods are implemented; + + b) Invoke the sendMessageInTransaction() method with the RocketMQTemplate API. Note: The first parameter of this method is correlated with the txProducerGroup attribute of @RocketMQTransactionListener. It can be null if using the default transaction producer group. + +1. How do I create more than one RocketMQTemplate with a different name-server or other specific properties? + ```java + // Step1. Define an extra RocketMQTemplate with required properties, note, the 'nameServer' property must be different from the value of global + // Spring configuration 'rocketmq.name-server', other properties are optionally defined, they will use the global configuration + // definition by default. + + // The RocketMQTemplate's Spring Bean name is 'extRocketMQTemplate', same with the simplified class name (Initials lowercase) + @ExtRocketMQTemplateConfiguration(nameServer="127.0.0.1:9876" + , ... // override other specific properties if needed + ) + public class ExtRocketMQTemplate extends RocketMQTemplate { + // keep the body empty + } + + + // Step2. Use the extra RocketMQTemplate. e.g. + @Resource(name = "extRocketMQTemplate") // Must define the name to qualify to extra-defined RocketMQTemplate bean. + private RocketMQTemplate extRocketMQTemplate; + // you can use the template as normal. + + ``` + +1. How do I create a consumer Listener with different name-server other than the global Spring configuration 'rocketmq.name-server' ? + ```java + @Service + @RocketMQMessageListener( + nameServer = "NEW-NAMESERVER-LIST", // define new nameServer list + topic = "test-topic-1", + consumerGroup = "my-consumer_test-topic-1", + enableMsgTrace = true, + customizedTraceTopic = "my-trace-topic" + ) + public class MyNameServerConsumer implements RocketMQListener { + ... + } + ``` \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/README_zh_CN.md b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/README_zh_CN.md new file mode 100644 index 000000000..fe26aa8ba --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/README_zh_CN.md @@ -0,0 +1,391 @@ +# RocketMQ-Spring [![Build Status](https://travis-ci.org/apache/rocketmq-spring.svg?branch=master)](https://travis-ci.org/apache/rocketmq-spring) + +[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.rocketmq/rocketmq-spring-all/badge.svg)](https://search.maven.org/search?q=g:org.apache.rocketmq%20AND%20a:rocketmq-spring-all) +[![GitHub release](https://img.shields.io/badge/release-download-orange.svg)](https://github.com/apache/rocketmq-spring/releases) +[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) + +[English](./README.md) + +帮助开发者在[Spring Boot](http://projects.spring.io/spring-boot/)中快速集成[RocketMQ](http://rocketmq.apache.org/)。支持Spring Message规范,方便开发者从其它MQ快速切换到RocketMQ。 + +## 如何贡献和帮助社区 + +我们永远欢迎开发者的帮助来使这个项目更加完善,无论是小的文档还是大的功能新特性,请参考RocketMQ的主站了解[细节](http://rocketmq.apache.org/docs/how-to-contribute/) + +## 前提条件 +- JDK 1.8 and above +- [Maven](http://maven.apache.org/) 3.0 and above + +功能特性: + +- [x] 同步发送 +- [x] 同步顺序发送 +- [x] 同步批量发送 +- [x] 异步发送 +- [x] 异步顺序发送 +- [x] 顺序消费 +- [x] 并发消费(广播/集群) +- [x] one-way方式发送 +- [x] 事务方式发送 +- [x] 消息轨迹 +- [x] ACL +- [ ] pull消费 + +## Quick Start + +下面列出来了一些关键点,完整的示例请参考: [rocketmq-spring-boot-samples](rocketmq-spring-boot-samples) + +注意:当前的RELEASE.VERSION=2.0.3 + +```xml + + + org.apache.rocketmq + rocketmq-spring-boot-starter + ${RELEASE.VERSION} + +``` + +### 发送消息 + +```properties +## application.properties +rocketmq.name-server=127.0.0.1:9876 +rocketmq.producer.group=my-group +``` + +> 注意: +> +> 请将上述示例配置中的`127.0.0.1:9876`替换成真实RocketMQ的NameServer地址与端口 + +```java +@SpringBootApplication +public class ProducerApplication implements CommandLineRunner{ + @Resource + private RocketMQTemplate rocketMQTemplate; + + public static void main(String[] args){ + SpringApplication.run(ProducerApplication.class, args); + } + + public void run(String... args) throws Exception { + rocketMQTemplate.convertAndSend("test-topic-1", "Hello, World!"); + rocketMQTemplate.send("test-topic-1", MessageBuilder.withPayload("Hello, World! I'm from spring message").build()); + rocketMQTemplate.convertAndSend("test-topic-2", new OrderPaidEvent("T_001", new BigDecimal("88.00"))); + +// rocketMQTemplate.destroy(); // notes: once rocketMQTemplate be destroyed, you can not send any message again with this rocketMQTemplate + } + + @Data + @AllArgsConstructor + public class OrderPaidEvent implements Serializable{ + private String orderId; + + private BigDecimal paidMoney; + } +} +``` + +### 在发送客户端发送事务性消息并且实现回查Listener +```java +@SpringBootApplication +public class ProducerApplication implements CommandLineRunner{ + @Resource + private RocketMQTemplate rocketMQTemplate; + + public static void main(String[] args){ + SpringApplication.run(ProducerApplication.class, args); + } + + public void run(String... args) throws Exception { + try { + // Build a SpringMessage for sending in transaction + Message msg = MessageBuilder.withPayload(..)... + // In sendMessageInTransaction(), the first parameter transaction name ("test") + // must be same with the @RocketMQTransactionListener's member field 'transName' + rocketMQTemplate.sendMessageInTransaction("test", "test-topic" msg, null); + } catch (MQClientException e) { + e.printStackTrace(System.out); + } + } + + // Define transaction listener with the annotation @RocketMQTransactionListener + @RocketMQTransactionListener(transName="test") + class TransactionListenerImpl implements RocketMQLocalTransactionListener { + @Override + public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { + // ... local transaction process, return bollback, commit or unknown + return RocketMQLocalTransactionState.UNKNOWN; + } + + @Override + public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { + // ... check transaction status and return bollback, commit or unknown + return RocketMQLocalTransactionState.COMMIT; + } + } +} +``` + +> 更多发送相关配置 +> +> ```properties +> rocketmq.producer.send-message-timeout=300000 +> rocketmq.producer.compress-message-body-threshold=4096 +> rocketmq.producer.max-message-size=4194304 +> rocketmq.producer.retry-times-when-send-async-failed=0 +> rocketmq.producer.retry-next-server=true +> rocketmq.producer.retry-times-when-send-failed=2 +> ``` + + +### 接收消息 + +```properties +## application.properties +rocketmq.name-server=127.0.0.1:9876 +``` + +> 注意: +> +> 请将上述示例配置中的`127.0.0.1:9876`替换成真实RocketMQ的NameServer地址与端口 + +```java +@SpringBootApplication +public class ConsumerApplication{ + + public static void main(String[] args){ + SpringApplication.run(ConsumerApplication.class, args); + } + + @Slf4j + @Service + @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1") + public class MyConsumer1 implements RocketMQListener{ + public void onMessage(String message) { + log.info("received message: {}", message); + } + } + + @Slf4j + @Service + @RocketMQMessageListener(topic = "test-topic-2", consumerGroup = "my-consumer_test-topic-2") + public class MyConsumer2 implements RocketMQListener{ + public void onMessage(OrderPaidEvent orderPaidEvent) { + log.info("received orderPaidEvent: {}", orderPaidEvent); + } + } +} +``` + + +> 更多消费相关配置 +> +> see: [RocketMQMessageListener](rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQMessageListener.java) + +### 消息轨迹 + +Producer 端要想使用消息轨迹,需要多配置两个配置项: + +```properties +## application.properties +rocketmq.name-server=127.0.0.1:9876 +rocketmq.producer.group=my-group + +rocketmq.producer.enable-msg-trace=true +rocketmq.producer.customized-trace-topic=my-trace-topic +``` + +Consumer 端消息轨迹的功能需要在 `@RocketMQMessageListener` 中进行配置对应的属性: + +``` +@Service +@RocketMQMessageListener( + topic = "test-topic-1", + consumerGroup = "my-consumer_test-topic-1", + enableMsgTrace = true, + customizedTraceTopic = "my-trace-topic" +) +public class MyConsumer implements RocketMQListener { + ... +} +``` + +> 注意: +> +> 默认情况下 Producer 和 Consumer 的消息轨迹功能是开启的且 trace-topic 为 RMQ_SYS_TRACE_TOPIC +> Consumer 端的消息轨迹 trace-topic 可以在配置文件中配置 `rocketmq.consumer.customized-trace-topic` 配置项,不需要为在每个 `@RocketMQTransactionListener` 配置 + + +### ACL + +Producer 端要想使用 ACL 功能,需要多配置两个配置项: + +```properties +## application.properties +rocketmq.name-server=127.0.0.1:9876 +rocketmq.producer.group=my-group + +rocketmq.producer.access-key=AK +rocketmq.producer.secret-key=SK +``` + +事务消息的发送需要在 `@RocketMQTransactionListener` 注解里配置上 AK/SK: + +``` +@RocketMQTransactionListener( + txProducerGroup = "test, + accessKey = "AK", + secretKey = "SK" +) +class TransactionListenerImpl implements RocketMQLocalTransactionListener { + ... +} +``` + +> 注意: +> +> 可以不用为每个 `@RocketMQTransactionListener` 注解配置 AK/SK,在配置文件中配置 `rocketmq.producer.access-key` 和 `rocketmq.producer.secret-key` 配置项,这两个配置项的值就是默认值 + +Consumer 端 ACL 功能需要在 `@RocketMQMessageListener` 中进行配置 + +``` +@Service +@RocketMQMessageListener( + topic = "test-topic-1", + consumerGroup = "my-consumer_test-topic-1", + accessKey = "AK", + secretKey = "SK" +) +public class MyConsumer implements RocketMQListener { + ... +} +``` + +> 注意: +> +> 可以不用为每个 `@RocketMQMessageListener` 注解配置 AK/SK,在配置文件中配置 `rocketmq.consumer.access-key` 和 `rocketmq.consumer.secret-key` 配置项,这两个配置项的值就是默认值 + +## FAQ + +1. 生产环境有多个`nameserver`该如何连接? + + `rocketmq.name-server`支持配置多个`nameserver`地址,采用`;`分隔即可。例如:`172.19.0.1:9876;172.19.0.2:9876` + +1. `rocketMQTemplate`在什么时候被销毁? + + 开发者在项目中使用`rocketMQTemplate`发送消息时,不需要手动执行`rocketMQTemplate.destroy()`方法, `rocketMQTemplate`会在spring容器销毁时自动销毁。 + +1. 启动报错:`Caused by: org.apache.rocketmq.client.exception.MQClientException: The consumer group[xxx] has been created before, specify another name please` + + RocketMQ在设计时就不希望一个消费者同时处理多个类型的消息,因此同一个`consumerGroup`下的consumer职责应该是一样的,不要干不同的事情(即消费多个topic)。建议`consumerGroup`与`topic`一一对应。 + +1. 发送的消息内容体是如何被序列化与反序列化的? + + RocketMQ的消息体都是以`byte[]`方式存储。当业务系统的消息内容体如果是`java.lang.String`类型时,统一按照`utf-8`编码转成`byte[]`;如果业务系统的消息内容为非`java.lang.String`类型,则采用[jackson-databind](https://github.com/FasterXML/jackson-databind)序列化成`JSON`格式的字符串之后,再统一按照`utf-8`编码转成`byte[]`。 + +1. 如何指定topic的`tags`? + + RocketMQ的最佳实践中推荐:一个应用尽可能用一个Topic,消息子类型用`tags`来标识,`tags`可以由应用自由设置。 + 在使用`rocketMQTemplate`发送消息时,通过设置发送方法的`destination`参数来设置消息的目的地,`destination`的格式为`topicName:tagName`,`:`前面表示topic的名称,后面表示`tags`名称。 + + > 注意: + > + > `tags`从命名来看像是一个复数,但发送消息时,目的地只能指定一个topic下的一个`tag`,不能指定多个。 + +1. 发送消息时如何设置消息的`key`? + + 可以通过重载的`xxxSend(String destination, Message msg, ...)`方法来发送消息,指定`msg`的`headers`来完成。示例: + + ```java + Message message = MessageBuilder.withPayload(payload).setHeader(MessageConst.PROPERTY_KEYS, msgId).build(); + rocketMQTemplate.send("topic-test", message); + ``` + + 同理还可以根据上面的方式来设置消息的`FLAG`、`WAIT_STORE_MSG_OK`以及一些用户自定义的其它头信息。 + + > 注意: + > + > 在将Spring的Message转化为RocketMQ的Message时,为防止`header`信息与RocketMQ的系统属性冲突,在所有`header`的名称前面都统一添加了前缀`USERS_`。因此在消费时如果想获取自定义的消息头信息,请遍历头信息中以`USERS_`开头的key即可。 + +1. 消费消息时,除了获取消息`payload`外,还想获取RocketMQ消息的其它系统属性,需要怎么做? + + 消费者在实现`RocketMQListener`接口时,只需要起泛型为`MessageExt`即可,这样在`onMessage`方法将接收到RocketMQ原生的`MessageExt`消息。 + + ```java + @Slf4j + @Service + @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1") + public class MyConsumer2 implements RocketMQListener{ + public void onMessage(MessageExt messageExt) { + log.info("received messageExt: {}", messageExt); + } + } + ``` + +1. 如何指定消费者从哪开始消费消息,或开始消费的位置? + + 消费者默认开始消费的位置请参考:[RocketMQ FAQ](http://rocketmq.apache.org/docs/faq/)。 + 若想自定义消费者开始的消费位置,只需在消费者类添加一个`RocketMQPushConsumerLifecycleListener`接口的实现即可。 示例如下: + + ```java + @Slf4j + @Service + @RocketMQMessageListener(topic = "test-topic-1", consumerGroup = "my-consumer_test-topic-1") + public class MyConsumer1 implements RocketMQListener, RocketMQPushConsumerLifecycleListener { + @Override + public void onMessage(String message) { + log.info("received message: {}", message); + } + + @Override + public void prepareStart(final DefaultMQPushConsumer consumer) { + // set consumer consume message from now + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP); + consumer.setConsumeTimestamp(UtilAll.timeMillisToHumanString3(System.currentTimeMillis())); + } + } + ``` + + 同理,任何关于`DefaultMQPushConsumer`的更多其它其它配置,都可以采用上述方式来完成。 + +1. 如何发送事务消息(即半消息支持分布式事务)? + 在客户端,首先用户需要实现RocketMQLocalTransactionListener接口,并在接口类上注解声明@RocketMQTransactionListener,实现确认和回查方法;然后再使用资源模板RocketMQTemplate, + 调用方法sendMessageInTransaction()来进行消息的发布。 注意:这个方法通过指定发送者组名与具体的声明了txProducerGroup的TransactionListener进行关联,您也可以不指定这个值,从而使用默认的事务发送者组。 + +1. 如何声明不同name-server或者其他特定的属性来定义非标的RocketMQTemplate? + ```java + // 第一步: 定义非标的RocketMQTemplate使用你需要的属性,注意,这里的'nameServer'属性必须要定义,并且其取值不能与全局配置属性'rocketmq.name-server'相同 + // 也可以定义其他属性,如果不定义,它们取全局的配置属性值或默认值。 + + // 这个RocketMQTemplate的Spring Bean名是'extRocketMQTemplate', 与所定义的类名相同(但首字母小写) + @ExtRocketMQTemplateConfiguration(nameServer="127.0.0.1:9876" + , ... // 定义其他属性,如果有必要。 + ) + public class ExtRocketMQTemplate extends RocketMQTemplate { + //类里面不需要做任何修改 + } + + + // 第二步: 使用这个非标RocketMQTemplate + @Resource(name = "extRocketMQTemplate") // 这里必须定义name属性来指向上具体的Spring Bean. + private RocketMQTemplate extRocketMQTemplate; + // 接下来就可以正常使用这个extRocketMQTemplate了. + + ``` + +1. MessageListener消费端,是否可以指定不同的name-server而不是使用全局定义的'rocketmq.name-server'属性值 ? + + ```java + @Service + @RocketMQMessageListener( + nameServer = "NEW-NAMESERVER-LIST", // 可以使用这个optional属性来指定不同的name-server + topic = "test-topic-1", + consumerGroup = "my-consumer_test-topic-1", + enableMsgTrace = true, + customizedTraceTopic = "my-trace-topic" + ) + public class MyNameServerConsumer implements RocketMQListener { + ... + } + ``` \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/pom.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/pom.xml new file mode 100644 index 000000000..b5f533f25 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/pom.xml @@ -0,0 +1,222 @@ + + + + + 4.0.0 + + + org.apache + apache + 18 + + + org.apache.rocketmq + rocketmq-spring-all + 2.0.3 + pom + + Apache RocketMQ Spring Boot ${project.version} + Build for Apache RocketMQ Spring Boot Support + https://github.com/apache/rocketmq-spring + + + + git@github.com:apache/rocketmq-spring.git + scm:git:git@github.com:apache/rocketmq-spring.git + scm:git:git@github.com:apache/rocketmq-spring.git + rocketmq-spring-all-2.0.3 + + + + + Development List + dev-subscribe@rocketmq.apache.org + dev-unsubscribe@rocketmq.apache.org + dev@rocketmq.apache.org + + + User List + users-subscribe@rocketmq.apache.org + users-unsubscribe@rocketmq.apache.org + users@rocketmq.apache.org + + + Commits List + commits-subscribe@rocketmq.apache.org + commits-unsubscribe@rocketmq.apache.org + commits@rocketmq.apache.org + + + + + + Apache Software Foundation + http://www.apache.org + + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + A business-friendly OSS license + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + validate + validate + + src/main/resources + style/rmq_checkstyle.xml + UTF-8 + true + true + + + check + + + + + + org.jacoco + jacoco-maven-plugin + 0.7.8 + + + default-prepare-agent + + prepare-agent + + + ${project.build.directory}/jacoco.exec + + + + default-prepare-agent-integration + pre-integration-test + + prepare-agent-integration + + + ${project.build.directory}/jacoco-it.exec + failsafeArgLine + + + + default-report + + report + + + + default-report-integration + + report-integration + + + + + + maven-surefire-plugin + 2.19.1 + + 1 + 1 + true + + **/IT*.java + + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.4 + + + org.sonarsource.scanner.maven + sonar-maven-plugin + 3.0.2 + + + org.apache.rat + apache-rat-plugin + 0.12 + + + .gitignore + .travis.yml + CONTRIBUTING.md + **/README.md + **/README_zh_CN.md + .github/** + src/test/resources/certs/* + src/test/**/*.log + src/test/resources/META-INF/service/* + **/target/** + */*.iml + **/*/spring.factories + **/application.properties + + + + + org.eluder.coveralls + coveralls-maven-plugin + 4.3.0 + + + + + + + maven-assembly-plugin + 3.0.0 + + + + + + + + sonar-apache + + + https://builds.apache.org/analysis + + + + + + rocketmq-spring-boot-parent + rocketmq-spring-boot + rocketmq-spring-boot-starter + + + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-parent/pom.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-parent/pom.xml new file mode 100644 index 000000000..adc5878bb --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-parent/pom.xml @@ -0,0 +1,167 @@ + + + + + 4.0.0 + + + org.apache.rocketmq + rocketmq-spring-all + 2.0.3 + ../pom.xml + + + rocketmq-spring-boot-parent + pom + + RocketMQ Spring Boot Parent + Parent package for Apache RocketMQ Spring Boot Support + https://github.com/apache/rocketmq-spring + + + ${project.basedir}/.. + 2.0.5.RELEASE + 5.1.0.RELEASE + + 2.0.3 + + 4.5.1 + 1.7.25 + 2.9.7 + + 1.8 + @ + + UTF-8 + UTF-8 + ${java.version} + ${java.version} + -Xdoclint:none + jacoco + + ${project.basedir}/../test/target/jacoco-it.exec + file:**/generated-sources/**,**/test/** + + + + + + org.springframework.boot + spring-boot + ${spring.boot.version} + + + + org.springframework.boot + spring-boot-autoconfigure + ${spring.boot.version} + + + + org.springframework.boot + spring-boot-autoconfigure-processor + ${spring.boot.version} + + + + org.springframework.boot + spring-boot-configuration-processor + ${spring.boot.version} + + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot.version} + test + + + + org.springframework.boot + spring-boot-starter + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-validation + ${spring.boot.version} + + + + org.apache.rocketmq + rocketmq-spring-boot + ${rocketmq.spring.boot.version} + + + + org.apache.rocketmq + rocketmq-client + ${rocketmq-version} + + + org.slf4j + slf4j-api + + + + + + org.apache.rocketmq + rocketmq-acl + ${rocketmq-version} + + + + org.springframework + spring-messaging + ${spring.version} + + + + org.springframework + spring-core + ${spring.version} + + + + org.springframework + spring-context + ${spring.version} + + + + org.springframework + spring-aop + ${spring.version} + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/LICENSE b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/LICENSE new file mode 100644 index 000000000..7a4a3ea24 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/README.md b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/README.md new file mode 100644 index 000000000..d1f2b2734 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/README.md @@ -0,0 +1,34 @@ +# rocketmq-spring-boot-samples + +[中文](./README_zh_CN.md) + +[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) + +It's a demo project for how to use [rocketmq-spring-boot](https://github.com/apache/rocketmq-spring) + +Run the test case locally +1. build and install the rocketmq-spring-boot-starter + +2. startup rocketmq according to quick-start, verify the namesvr and broker startup correctly, Note: DON'T do "Shutdown Servers" step. +http://rocketmq.apache.org/docs/quick-start/ + +3. create topics for the demo test cases +``` +bash bin/mqadmin updateTopic -c DefaultCluster -t string-topic +bash bin/mqadmin updateTopic -c DefaultCluster -t order-paid-topic +bash bin/mqadmin updateTopic -c DefaultCluster -t message-ext-topic +bash bin/mqadmin updateTopic -c DefaultCluster -t spring-transaction-topic +``` +4. run tests + +``` +# open a terminal, run produce +cd rocketmq-produce-demo +mvn clean package +java -jar target/rocketmq-produce-demo-0.0.1-SNAPSHOT.jar + +# open another terminal, run consume +cd rocketmq-consume-demo +mvn clean package +java -jar target/rocketmq-consume-demo-0.0.1-SNAPSHOT.jar +``` diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/README_zh_CN.md b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/README_zh_CN.md new file mode 100644 index 000000000..c8f27d1c4 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/README_zh_CN.md @@ -0,0 +1,40 @@ +# rocketmq-spring-boot-samples + +[English](./README.md) + +[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) + +这里是一个使用rocketmq-spring-boot-starter的例子。 [rocketmq-spring-boot](https://github.com/apache/rocketmq-spring) + + +## 在本地运行这个测试例子 + +1. 如上面注意项所述,需要开发者在本地build并安装rocketmq-spring-boot-starter + +2. 根据RocketMQ官网的quick-start来启动NameServer和Broker,并验证是否启动正确。注意: 测试期间不要停止Broker或者NameServer +http://rocketmq.apache.org/docs/quick-start/ + +3. 创建测试例子所需要的Topic +``` +cd YOUR_ROCKETMQ_HOME + +bash bin/mqadmin updateTopic -c DefaultCluster -t string-topic +bash bin/mqadmin updateTopic -c DefaultCluster -t order-paid-topic +bash bin/mqadmin updateTopic -c DefaultCluster -t message-ext-topic +bash bin/mqadmin updateTopic -c DefaultCluster -t spring-transaction-topic +``` + +4. 编译并运行测试例子 + +``` +# 打开一个终端窗口,编译并启动发送端 +cd rocketmq-produce-demo +mvn clean package +java -jar target/rocketmq-produce-demo-0.0.1-SNAPSHOT.jar + +# 打开另一个终端窗口,编译并启动消费端 +cd rocketmq-consume-demo +mvn clean package +java -jar target/rocketmq-consume-demo-0.0.1-SNAPSHOT.jar +``` +结合测试代码,观察窗口中消息的发送和接收情况 diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/pom.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/pom.xml new file mode 100644 index 000000000..e348e15c8 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/pom.xml @@ -0,0 +1,91 @@ + + + + + 4.0.0 + + org.apache.rocketmq + rocketmq-spring-boot-samples + pom + 0.0.1-SNAPSHOT + + RocketMQ Spring Boot Samples + Samples for RocketMQ Spring Boot + https://github.com/apache/rocketmq-spring + + + rocketmq-produce-demo + rocketmq-consume-demo + rocketmq-produce-acl-demo + rocketmq-consume-acl-demo + + + + 2.0.3 + + + + + org.apache.rocketmq + rocketmq-spring-boot-starter + ${rocketmq-spring-boot-starter-version} + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.17 + + + validate + validate + + ${disable.checks} + src/main/resources + style/rmq_checkstyle.xml + UTF-8 + true + true + + + check + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.0.RELEASE + + + + repackage + + + + + + + + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml new file mode 100644 index 000000000..47fc22128 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/pom.xml @@ -0,0 +1,31 @@ + + + + + 4.0.0 + + org.apache.rocketmq + rocketmq-spring-boot-samples + 0.0.1-SNAPSHOT + + + rocketmq-consume-acl-demo + + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ACLStringConsumer.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ACLStringConsumer.java new file mode 100644 index 000000000..fe99d3898 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ACLStringConsumer.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot; + +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.stereotype.Service; + +/** + * RocketMQMessageListener + */ +@Service +@RocketMQMessageListener( + topic = "normal_topic_define_in_Aliware_MQ", + consumerGroup = "group_define_in_Aliware_MQ" + //accessKey = "AK" // It will read by `rocketmq.consumer.access-key` key + //secretKey = "SK" // It will read by `rocketmq.consumer.access-key` key + ) +public class ACLStringConsumer implements RocketMQListener { + @Override + public void onMessage(String message) { + System.out.printf("------- ACL StringConsumer received: %s \n", message); + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ACLStringTransactionalConsumer.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ACLStringTransactionalConsumer.java new file mode 100644 index 000000000..342f44bb1 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ACLStringTransactionalConsumer.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot; + +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.stereotype.Service; + +/** + * StringTransactionalConsumer + */ +@Service +@RocketMQMessageListener( + topic = "${demo.rocketmq.transTopic}", + consumerGroup = "group_define_in_Aliware_MQ", + accessKey = "AK", // if accessKey is empty, it will read by `rocketmq.consumer.access-key` key + secretKey = "SK" // if accessKey is empty, it will read by `rocketmq.consumer.secret-key` key + ) +public class ACLStringTransactionalConsumer implements RocketMQListener { + @Override + public void onMessage(String message) { + System.out.printf("------- ACL StringTransactionalConsumer received: %s \n", message); + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerACLApplication.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerACLApplication.java new file mode 100644 index 000000000..3bf266b1b --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerACLApplication.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * ConsumerApplication + */ +@SpringBootApplication +public class ConsumerACLApplication { + + public static void main(String[] args) { + SpringApplication.run(ConsumerACLApplication.class, args); + } +} + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/resources/application.properties b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/resources/application.properties new file mode 100644 index 000000000..7ca3c4297 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-acl-demo/src/main/resources/application.properties @@ -0,0 +1,10 @@ +spring.application.name=rocketmq-consume-acl-demo + +rocketmq.name-server=Endpoint_of_Aliware_MQ +rocketmq.topic=normal_topic_define_in_Aliware_MQ + +# properties used in application code +demo.rocketmq.transTopic=transaction_topic_define_in_Aliware_MQ + +rocketmq.consumer.access-key=AK +rocketmq.consumer.secret-key=SK \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml new file mode 100644 index 000000000..4093170bd --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/pom.xml @@ -0,0 +1,31 @@ + + + + + 4.0.0 + + org.apache.rocketmq + rocketmq-spring-boot-samples + 0.0.1-SNAPSHOT + + + rocketmq-consume-demo + + \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerApplication.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerApplication.java new file mode 100644 index 000000000..e4fbc8c90 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/ConsumerApplication.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * ConsumerApplication + */ +@SpringBootApplication +public class ConsumerApplication { + + public static void main(String[] args) { + SpringApplication.run(ConsumerApplication.class, args); + } +} + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/Checker.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/Checker.java new file mode 100644 index 000000000..608df1b2a --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/Checker.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot.consumer; + +import org.apache.rocketmq.client.producer.LocalTransactionState; +import org.apache.rocketmq.client.producer.TransactionListener; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageExt; + +/** + * Note: This is a nagitive testing. It aims to tell user the fact that + * the @RocketMQTransactionListener can not be used on consumer side!!! + * + *

How to try it? just uncomment the annotation declaration, then compile + * and run the consumer, it will fail to start. + */ + +//@RocketMQTransactionListener +public class Checker implements TransactionListener { + @Override + public LocalTransactionState executeLocalTransaction(Message message, Object o) { + return null; + } + + @Override + public LocalTransactionState checkLocalTransaction(MessageExt messageExt) { + return null; + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/MessageExtConsumer.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/MessageExtConsumer.java new file mode 100644 index 000000000..59ef26306 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/MessageExtConsumer.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot.consumer; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.common.UtilAll; +import org.apache.rocketmq.common.consumer.ConsumeFromWhere; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener; +import org.springframework.stereotype.Service; + +/** + * MessageExtConsumer, consume listener impl class. + */ +@Service +@RocketMQMessageListener(topic = "message-ext-topic", selectorExpression = "tag1", consumerGroup = "${spring.application.name}-message-ext-consumer") +public class MessageExtConsumer implements RocketMQListener, RocketMQPushConsumerLifecycleListener { + @Override + public void onMessage(MessageExt message) { + System.out.printf("------- MessageExtConsumer received message, msgId: %s, body:%s \n", message.getMsgId(), new String(message.getBody())); + } + + @Override + public void prepareStart(DefaultMQPushConsumer consumer) { + // set consumer consume message from now + consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_TIMESTAMP); + consumer.setConsumeTimestamp(UtilAll.timeMillisToHumanString3(System.currentTimeMillis())); + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/OrderPaidEventConsumer.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/OrderPaidEventConsumer.java new file mode 100644 index 000000000..677e0eab5 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/OrderPaidEventConsumer.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot.consumer; + +import org.apache.rocketmq.samples.springboot.domain.OrderPaidEvent; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.stereotype.Service; + +/** + * OrderPaidEventConsumer + */ +@Service +@RocketMQMessageListener(topic = "${demo.rocketmq.orderTopic}", consumerGroup = "order-paid-consumer") +public class OrderPaidEventConsumer implements RocketMQListener { + + @Override + public void onMessage(OrderPaidEvent orderPaidEvent) { + System.out.printf("------- OrderPaidEventConsumer received: %s \n", orderPaidEvent); + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumer.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumer.java new file mode 100644 index 000000000..2b90c69d3 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumer.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot.consumer; + +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.stereotype.Service; + +/** + * RocketMQMessageListener + */ +@Service +@RocketMQMessageListener(topic = "${demo.rocketmq.topic}", consumerGroup = "string_consumer") +public class StringConsumer implements RocketMQListener { + @Override + public void onMessage(String message) { + System.out.printf("------- StringConsumer received: %s \n", message); + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerNewNS.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerNewNS.java new file mode 100644 index 000000000..5d2c8727d --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringConsumerNewNS.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot.consumer; + +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.stereotype.Service; + +/** + * RocketMQMessageListener + */ +@Service +@RocketMQMessageListener(nameServer = "${demo.rocketmq.myNameServer}", topic = "${demo.rocketmq.topic}", consumerGroup = "string_consumer") +public class StringConsumerNewNS implements RocketMQListener { + @Override + public void onMessage(String message) { + System.out.printf("------- StringConsumerNewNS received: %s \n", message); + } +} \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringTransactionalConsumer.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringTransactionalConsumer.java new file mode 100644 index 000000000..be5d08d85 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/consumer/StringTransactionalConsumer.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot.consumer; + +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.stereotype.Service; + +/** + * StringTransactionalConsumer + */ +@Service +@RocketMQMessageListener(topic = "${demo.rocketmq.transTopic}", consumerGroup = "string_trans_consumer") +public class StringTransactionalConsumer implements RocketMQListener { + @Override + public void onMessage(String message) { + System.out.printf("------- StringTransactionalConsumer received: %s \n", message); + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java new file mode 100644 index 000000000..812ab83e7 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot.domain; + +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * OrderPaidEvent + */ +public class OrderPaidEvent implements Serializable { + private String orderId; + + private BigDecimal paidMoney; + + public OrderPaidEvent() { + } + + public OrderPaidEvent(String orderId, BigDecimal paidMoney) { + this.orderId = orderId; + this.paidMoney = paidMoney; + } + + public String getOrderId() { + return orderId; + } + + public void setOrderId(String orderId) { + this.orderId = orderId; + } + + public BigDecimal getPaidMoney() { + return paidMoney; + } + + public void setPaidMoney(BigDecimal paidMoney) { + this.paidMoney = paidMoney; + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/resources/application.properties b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/resources/application.properties new file mode 100644 index 000000000..404cb1023 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-consume-demo/src/main/resources/application.properties @@ -0,0 +1,12 @@ +spring.application.name=rocketmq-consume-demo + +rocketmq.name-server=localhost:9876 + +# properties used in application code +demo.rocketmq.topic=string-topic +demo.rocketmq.orderTopic=order-paid-topic +demo.rocketmq.msgExtTopic=message-ext-topic +demo.rocketmq.transTopic=spring-transaction-topic + +# another nameserver different global +demo.rocketmq.myNameServer=127.0.0.1:9876 \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml new file mode 100644 index 000000000..9193d9861 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/pom.xml @@ -0,0 +1,32 @@ + + + + + 4.0.0 + + org.apache.rocketmq + rocketmq-spring-boot-samples + 0.0.1-SNAPSHOT + + + rocketmq-produce-acl-demo + + + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerACLApplication.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerACLApplication.java new file mode 100644 index 000000000..1c4035455 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerACLApplication.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.annotation.Resource; + +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.apache.rocketmq.spring.support.RocketMQHeaders; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessagingException; +import org.springframework.messaging.support.MessageBuilder; + +/** + * Producer, using RocketMQTemplate sends a variety of messages + */ +@SpringBootApplication +public class ProducerACLApplication implements CommandLineRunner { + private static final String TX_PGROUP_NAME = "myTxProducerGroup"; + @Resource + private RocketMQTemplate rocketMQTemplate; + @Value("${demo.rocketmq.transTopic}") + private String springTransTopic; + @Value("${demo.rocketmq.topic}") + private String springTopic; + + public static void main(String[] args) { + SpringApplication.run(ProducerACLApplication.class, args); + } + + @Override + public void run(String... args) throws Exception { + // Send string + SendResult sendResult = rocketMQTemplate.syncSend(springTopic + ":acl", "Hello, ACL Msg!"); + System.out.printf("syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); + + // Send string with spring Message + sendResult = rocketMQTemplate.syncSend(springTopic, MessageBuilder.withPayload("Hello, World! I'm from spring message & ACL Msg").build()); + System.out.printf("syncSend2 to topic %s sendResult=%s %n", springTopic, sendResult); + + //Send transactional messages + testTransaction(); + } + + + private void testTransaction() throws MessagingException { + String[] tags = new String[]{"TagA", "TagB", "TagC", "TagD", "TagE"}; + for (int i = 0; i < 10; i++) { + try { + + Message msg = MessageBuilder.withPayload("Hello RocketMQ " + i). + setHeader(RocketMQHeaders.KEYS, "KEY_" + i).build(); + SendResult sendResult = rocketMQTemplate.sendMessageInTransaction(TX_PGROUP_NAME, + springTransTopic + ":" + tags[i % tags.length], msg, null); + System.out.printf("------ send Transactional msg body = %s , sendResult=%s %n", + msg.getPayload(), sendResult.getSendStatus()); + + Thread.sleep(10); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @RocketMQTransactionListener( + txProducerGroup = TX_PGROUP_NAME, + accessKey = "AK", // if not setting, it will read by `rocketmq.producer.access-key` key + secretKey = "SK" // if not setting, it will read by `rocketmq.producer.secret-key` key + ) + class TransactionListenerImpl implements RocketMQLocalTransactionListener { + private AtomicInteger transactionIndex = new AtomicInteger(0); + + private ConcurrentHashMap localTrans = new ConcurrentHashMap(); + + @Override + public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { + String transId = (String)msg.getHeaders().get(RocketMQHeaders.TRANSACTION_ID); + System.out.printf("#### executeLocalTransaction is executed, msgTransactionId=%s %n", + transId); + int value = transactionIndex.getAndIncrement(); + int status = value % 3; + localTrans.put(transId, status); + if (status == 0) { + // Return local transaction with success(commit), in this case, + // this message will not be checked in checkLocalTransaction() + System.out.printf(" # COMMIT # Simulating msg %s related local transaction exec succeeded! ### %n", msg.getPayload()); + return RocketMQLocalTransactionState.COMMIT; + } + + if (status == 1) { + // Return local transaction with failure(rollback) , in this case, + // this message will not be checked in checkLocalTransaction() + System.out.printf(" # ROLLBACK # Simulating %s related local transaction exec failed! %n", msg.getPayload()); + return RocketMQLocalTransactionState.ROLLBACK; + } + + System.out.printf(" # UNKNOW # Simulating %s related local transaction exec UNKNOWN! \n"); + return RocketMQLocalTransactionState.UNKNOWN; + } + + @Override + public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { + String transId = (String)msg.getHeaders().get(RocketMQHeaders.TRANSACTION_ID); + RocketMQLocalTransactionState retState = RocketMQLocalTransactionState.COMMIT; + Integer status = localTrans.get(transId); + if (null != status) { + switch (status) { + case 0: + retState = RocketMQLocalTransactionState.UNKNOWN; + break; + case 1: + retState = RocketMQLocalTransactionState.COMMIT; + break; + case 2: + retState = RocketMQLocalTransactionState.COMMIT; + break; + } + } + System.out.printf("------ !!! checkLocalTransaction is executed once," + + " msgTransactionId=%s, TransactionState=%s status=%s %n", + transId, retState, status); + return retState; + } + } + +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/resources/application.properties b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/resources/application.properties new file mode 100644 index 000000000..dd49d0dcf --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-acl-demo/src/main/resources/application.properties @@ -0,0 +1,7 @@ +rocketmq.name-server=Endpoint_of_Aliware_MQ +rocketmq.producer.group=my-group1 +rocketmq.producer.access-key=AK +rocketmq.producer.secret-key=SK + +demo.rocketmq.topic=normal_topic_define_in_Aliware_MQ +demo.rocketmq.transTopic=transaction_topic_define_in_Aliware_MQ diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml new file mode 100644 index 000000000..0ef364d11 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/pom.xml @@ -0,0 +1,32 @@ + + + + + 4.0.0 + + org.apache.rocketmq + rocketmq-spring-boot-samples + 0.0.1-SNAPSHOT + + + rocketmq-produce-demo + + + \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ExtRocketMQTemplate.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ExtRocketMQTemplate.java new file mode 100644 index 000000000..7a7855245 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ExtRocketMQTemplate.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.samples.springboot; + +import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; +import org.apache.rocketmq.spring.core.RocketMQTemplate; + +@ExtRocketMQTemplateConfiguration(nameServer = "${demo.rocketmq.extNameServer}") +public class ExtRocketMQTemplate extends RocketMQTemplate { +} \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerApplication.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerApplication.java new file mode 100644 index 000000000..9e49170e8 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/ProducerApplication.java @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.samples.springboot; + +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.samples.springboot.domain.OrderPaidEvent; +import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.apache.rocketmq.spring.support.RocketMQHeaders; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessagingException; +import org.springframework.messaging.support.MessageBuilder; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Producer, using RocketMQTemplate sends a variety of messages + */ +@SpringBootApplication +public class ProducerApplication implements CommandLineRunner { + private static final String TX_PGROUP_NAME = "myTxProducerGroup"; + @Resource + private RocketMQTemplate rocketMQTemplate; + @Value("${demo.rocketmq.transTopic}") + private String springTransTopic; + @Value("${demo.rocketmq.topic}") + private String springTopic; + @Value("${demo.rocketmq.orderTopic}") + private String orderPaidTopic; + @Value("${demo.rocketmq.msgExtTopic}") + private String msgExtTopic; + @Resource(name = "extRocketMQTemplate") + private RocketMQTemplate extRocketMQTemplate; + + public static void main(String[] args) { + SpringApplication.run(ProducerApplication.class, args); + } + + @Override + public void run(String... args) throws Exception { + // Send string + SendResult sendResult = rocketMQTemplate.syncSend(springTopic, "Hello, World!"); + System.out.printf("syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); + + // Use the extRocketMQTemplate + sendResult = extRocketMQTemplate.syncSend(springTopic, "Hello, World!"); + System.out.printf("extRocketMQTemplate.syncSend1 to topic %s sendResult=%s %n", springTopic, sendResult); + + // Send string with spring Message + sendResult = rocketMQTemplate.syncSend(springTopic, MessageBuilder.withPayload("Hello, World! I'm from spring message").build()); + System.out.printf("syncSend2 to topic %s sendResult=%s %n", springTopic, sendResult); + + // Send user-defined object + rocketMQTemplate.asyncSend(orderPaidTopic, new OrderPaidEvent("T_001", new BigDecimal("88.00")), new SendCallback() { + public void onSuccess(SendResult var1) { + System.out.printf("async onSucess SendResult=%s %n", var1); + } + + public void onException(Throwable var1) { + System.out.printf("async onException Throwable=%s %n", var1); + } + + }); + + // Send message with special tag + rocketMQTemplate.convertAndSend(msgExtTopic + ":tag0", "I'm from tag0"); // tag0 will not be consumer-selected + System.out.printf("syncSend topic %s tag %s %n", msgExtTopic, "tag0"); + rocketMQTemplate.convertAndSend(msgExtTopic + ":tag1", "I'm from tag1"); + System.out.printf("syncSend topic %s tag %s %n", msgExtTopic, "tag1"); + + + // Send a batch of strings + testBatchMessages(); + + // Send transactional messages + testTransaction(); + } + + private void testBatchMessages() { + List msgs = new ArrayList(); + for (int i = 0; i < 10; i++) { + msgs.add(MessageBuilder.withPayload("Hello RocketMQ Batch Msg#" + i). + setHeader(RocketMQHeaders.KEYS, "KEY_" + i).build()); + } + + SendResult sr = rocketMQTemplate.syncSend(springTopic, msgs, 60000); + + System.out.printf("--- Batch messages send result :" + sr); + } + + + private void testTransaction() throws MessagingException { + String[] tags = new String[]{"TagA", "TagB", "TagC", "TagD", "TagE"}; + for (int i = 0; i < 10; i++) { + try { + + Message msg = MessageBuilder.withPayload("Hello RocketMQ " + i). + setHeader(RocketMQHeaders.KEYS, "KEY_" + i).build(); + SendResult sendResult = rocketMQTemplate.sendMessageInTransaction(TX_PGROUP_NAME, + springTransTopic + ":" + tags[i % tags.length], msg, null); + System.out.printf("------ send Transactional msg body = %s , sendResult=%s %n", + msg.getPayload(), sendResult.getSendStatus()); + + Thread.sleep(10); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @RocketMQTransactionListener(txProducerGroup = TX_PGROUP_NAME) + class TransactionListenerImpl implements RocketMQLocalTransactionListener { + private AtomicInteger transactionIndex = new AtomicInteger(0); + + private ConcurrentHashMap localTrans = new ConcurrentHashMap(); + + @Override + public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) { + String transId = (String)msg.getHeaders().get(RocketMQHeaders.TRANSACTION_ID); + System.out.printf("#### executeLocalTransaction is executed, msgTransactionId=%s %n", + transId); + int value = transactionIndex.getAndIncrement(); + int status = value % 3; + localTrans.put(transId, status); + if (status == 0) { + // Return local transaction with success(commit), in this case, + // this message will not be checked in checkLocalTransaction() + System.out.printf(" # COMMIT # Simulating msg %s related local transaction exec succeeded! ### %n", msg.getPayload()); + return RocketMQLocalTransactionState.COMMIT; + } + + if (status == 1) { + // Return local transaction with failure(rollback) , in this case, + // this message will not be checked in checkLocalTransaction() + System.out.printf(" # ROLLBACK # Simulating %s related local transaction exec failed! %n", msg.getPayload()); + return RocketMQLocalTransactionState.ROLLBACK; + } + + System.out.printf(" # UNKNOW # Simulating %s related local transaction exec UNKNOWN! \n"); + return RocketMQLocalTransactionState.UNKNOWN; + } + + @Override + public RocketMQLocalTransactionState checkLocalTransaction(Message msg) { + String transId = (String)msg.getHeaders().get(RocketMQHeaders.TRANSACTION_ID); + RocketMQLocalTransactionState retState = RocketMQLocalTransactionState.COMMIT; + Integer status = localTrans.get(transId); + if (null != status) { + switch (status) { + case 0: + retState = RocketMQLocalTransactionState.UNKNOWN; + break; + case 1: + retState = RocketMQLocalTransactionState.COMMIT; + break; + case 2: + retState = RocketMQLocalTransactionState.ROLLBACK; + break; + } + } + System.out.printf("------ !!! checkLocalTransaction is executed once," + + " msgTransactionId=%s, TransactionState=%s status=%s %n", + transId, retState, status); + return retState; + } + } + +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java new file mode 100644 index 000000000..feaac0d16 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/java/org/apache/rocketmq/samples/springboot/domain/OrderPaidEvent.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.samples.springboot.domain; + +import java.io.Serializable; +import java.math.BigDecimal; + +public class OrderPaidEvent implements Serializable { + private String orderId; + + private BigDecimal paidMoney; + + public OrderPaidEvent() { + } + + public OrderPaidEvent(String orderId, BigDecimal paidMoney) { + this.orderId = orderId; + this.paidMoney = paidMoney; + } + + public String getOrderId() { + return orderId; + } + + public void setOrderId(String orderId) { + this.orderId = orderId; + } + + public BigDecimal getPaidMoney() { + return paidMoney; + } + + public void setPaidMoney(BigDecimal paidMoney) { + this.paidMoney = paidMoney; + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties new file mode 100644 index 000000000..3a6850513 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/rocketmq-produce-demo/src/main/resources/application.properties @@ -0,0 +1,11 @@ +rocketmq.name-server=localhost:9876 +rocketmq.producer.group=my-group1 +rocketmq.producer.sendMessageTimeout=300000 + +# properties used in the application +demo.rocketmq.topic=string-topic +demo.rocketmq.orderTopic=order-paid-topic +demo.rocketmq.msgExtTopic=message-ext-topic +demo.rocketmq.transTopic=spring-transaction-topic + +demo.rocketmq.extNameServer=127.0.0.1:9876 \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/copyright/Apache.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/copyright/Apache.xml new file mode 100644 index 000000000..e3e3dec30 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/copyright/Apache.xml @@ -0,0 +1,23 @@ + + + + + + \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/copyright/profiles_settings.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/copyright/profiles_settings.xml new file mode 100644 index 000000000..747c7e2bf --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/copyright/profiles_settings.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/rmq_checkstyle.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/rmq_checkstyle.xml new file mode 100644 index 000000000..2e9658f4f --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/rmq_checkstyle.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/rmq_codeStyle.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/rmq_codeStyle.xml new file mode 100644 index 000000000..9db075e36 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot-samples/style/rmq_codeStyle.xml @@ -0,0 +1,157 @@ + + + + + + + \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/README.md b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/README.md new file mode 100644 index 000000000..a4d3022a0 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/README.md @@ -0,0 +1,7 @@ +# RocketMQ Spring Boot Support +This project provides auto-configuration for the following RocketMQ client: + +- [Produce and Consume Spring Message](../rocketmq-spring-boot-starter) +- [Send (halp) Message in Transaction](../rocketmq-spring-boot-starter) + +For details, please see sample code in the [rocketmq-spring-boot-samples](../rocketmq-spring-boot-samples) \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/pom.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/pom.xml new file mode 100644 index 000000000..b93e05cb4 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/pom.xml @@ -0,0 +1,102 @@ + + + + + 4.0.0 + + + org.apache.rocketmq + rocketmq-spring-boot-parent + 2.0.3 + ../rocketmq-spring-boot-parent/pom.xml + + + rocketmq-spring-boot + jar + + RocketMQ Spring Boot AutoConfigure + SRocketMQ Spring Boot AutoConfigure + https://github.com/apache/rocketmq-spring + + + + + org.slf4j + slf4j-api + + + org.springframework.boot + spring-boot + true + + + org.springframework.boot + spring-boot-autoconfigure + true + + + org.springframework.boot + spring-boot-autoconfigure-processor + true + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.apache.rocketmq + rocketmq-client + + + org.slf4j + slf4j-api + + + + + org.apache.rocketmq + rocketmq-acl + + + org.springframework + spring-messaging + + + org.springframework + spring-core + + + org.springframework + spring-context + + + org.springframework + spring-aop + + + com.fasterxml.jackson.core + jackson-databind + + + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ConsumeMode.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ConsumeMode.java new file mode 100644 index 000000000..1b9f35afb --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ConsumeMode.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.annotation; + +public enum ConsumeMode { + /** + * Receive asynchronously delivered messages concurrently + */ + CONCURRENTLY, + + /** + * Receive asynchronously delivered messages orderly. one queue, one thread + */ + ORDERLY +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ExtRocketMQTemplateConfiguration.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ExtRocketMQTemplateConfiguration.java new file mode 100644 index 000000000..c268b571e --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/ExtRocketMQTemplateConfiguration.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.annotation; + +import org.springframework.stereotype.Component; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Component +public @interface ExtRocketMQTemplateConfiguration { + /** + * The component name of the Producer configuration. + */ + String value() default ""; + + /** + * The property of "name-server". + */ + String nameServer(); + + /** + * Name of producer. + */ + String group() default "${rocketmq.producer.group:}"; + /** + * Millis of send message timeout. + */ + int sendMessageTimeout() default -1; + /** + * Compress message body threshold, namely, message body larger than 4k will be compressed on default. + */ + int compressMessageBodyThreshold() default -1; + /** + * 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. + */ + int retryTimesWhenSendFailed() default -1; + /** + *

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. + */ + int retryTimesWhenSendAsyncFailed() default -1; + /** + * Indicate whether to retry another broker on sending failure internally. + */ + boolean retryNextServer() default false; + /** + * Maximum allowed message size in bytes. + */ + int maxMessageSize() default -1; + /** + * The property of "access-key". + */ + String accessKey() default "${rocketmq.producer.accessKey:}"; + /** + * The property of "secret-key". + */ + String secretKey() default "${rocketmq.producer.secretKey:}"; + /** + * Switch flag instance for message trace. + */ + boolean enableMsgTrace() default true; + /** + * The name value of message trace topic.If you don't config,you can use the default trace topic name. + */ + String customizedTraceTopic() default "${rocketmq.producer.customized-trace-topic:}"; +} \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/MessageModel.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/MessageModel.java new file mode 100644 index 000000000..7de21879d --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/MessageModel.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.annotation; + +public enum MessageModel { + BROADCASTING("BROADCASTING"), + CLUSTERING("CLUSTERING"); + + private final String modeCN; + + MessageModel(String modeCN) { + this.modeCN = modeCN; + } + + public String getModeCN() { + return this.modeCN; + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQMessageListener.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQMessageListener.java new file mode 100644 index 000000000..f1c774858 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQMessageListener.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RocketMQMessageListener { + + String NAME_SERVER_PLACEHOLDER = "${rocketmq.name-server:}"; + String ACCESS_KEY_PLACEHOLDER = "${rocketmq.consumer.access-key:}"; + String SECRET_KEY_PLACEHOLDER = "${rocketmq.consumer.secret-key:}"; + String TRACE_TOPIC_PLACEHOLDER = "${rocketmq.consumer.customized-trace-topic:}"; + String ACCESS_CHANNEL_PLACEHOLDER = "${rocketmq.access-channel:}"; + + /** + * Consumers of the same role is required to have exactly same subscriptions and consumerGroup to correctly achieve + * load balance. It's required and needs to be globally unique. + * + * + * See here for further discussion. + */ + String consumerGroup(); + + /** + * Topic name. + */ + String topic(); + + /** + * Control how to selector message. + * + * @see SelectorType + */ + SelectorType selectorType() default SelectorType.TAG; + + /** + * Control which message can be select. Grammar please see {@link SelectorType#TAG} and {@link SelectorType#SQL92} + */ + String selectorExpression() default "*"; + + /** + * Control consume mode, you can choice receive message concurrently or orderly. + */ + ConsumeMode consumeMode() default ConsumeMode.CONCURRENTLY; + + /** + * Control message mode, if you want all subscribers receive message all message, broadcasting is a good choice. + */ + MessageModel messageModel() default MessageModel.CLUSTERING; + + /** + * Max consumer thread number. + */ + int consumeThreadMax() default 64; + + /** + * Max consumer timeout, default 30s. + */ + long consumeTimeout() default 30000L; + + /** + * The property of "access-key". + */ + String accessKey() default ACCESS_KEY_PLACEHOLDER; + + /** + * The property of "secret-key". + */ + String secretKey() default SECRET_KEY_PLACEHOLDER; + + /** + * Switch flag instance for message trace. + */ + boolean enableMsgTrace() default true; + + /** + * The name value of message trace topic.If you don't config,you can use the default trace topic name. + */ + String customizedTraceTopic() default TRACE_TOPIC_PLACEHOLDER; + + /** + * The property of "name-server". + */ + String nameServer() default NAME_SERVER_PLACEHOLDER; + + /** + * The property of "access-channel". + */ + String accessChannel() default ACCESS_CHANNEL_PLACEHOLDER; +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQTransactionListener.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQTransactionListener.java new file mode 100644 index 000000000..f3f874cf0 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/RocketMQTransactionListener.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.annotation; + +import org.apache.rocketmq.spring.config.RocketMQConfigUtils; +import org.springframework.stereotype.Component; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation is used over a class which implements interface + * org.apache.rocketmq.client.producer.TransactionListener. The class implements + * two methods for process callback events after the txProducer sends a transactional message. + *

Note: The annotation is used only on RocketMQ client producer side, it can not be used + * on consumer side. + */ +@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Component +public @interface RocketMQTransactionListener { + + /** + * Declare the txProducerGroup that is used to relate callback event to the listener, rocketMQTemplate must send a + * transactional message with the declared txProducerGroup. + *

+ *

It is suggested to use the default txProducerGroup if your system only needs to define a TransactionListener class. + */ + String txProducerGroup() default RocketMQConfigUtils.ROCKETMQ_TRANSACTION_DEFAULT_GLOBAL_NAME; + + /** + * Set ExecutorService params -- corePoolSize + */ + int corePoolSize() default 1; + + /** + * Set ExecutorService params -- maximumPoolSize + */ + int maximumPoolSize() default 1; + + /** + * Set ExecutorService params -- keepAliveTime + */ + long keepAliveTime() default 1000 * 60; //60ms + + /** + * Set ExecutorService params -- blockingQueueSize + */ + int blockingQueueSize() default 2000; + + /** + * The property of "access-key" + */ + String accessKey() default "${rocketmq.producer.access-key}"; + + /** + * The property of "secret-key" + */ + String secretKey() default "${rocketmq.producer.secret-key}"; +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/SelectorType.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/SelectorType.java new file mode 100644 index 000000000..97e8b7e78 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/annotation/SelectorType.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.annotation; + +import org.apache.rocketmq.common.filter.ExpressionType; + +public enum SelectorType { + + /** + * @see ExpressionType#TAG + */ + TAG, + + /** + * @see ExpressionType#SQL92 + */ + SQL92 +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java new file mode 100644 index 000000000..192bfc989 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ExtProducerResetConfiguration.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.autoconfigure; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.rocketmq.acl.common.AclClientRPCHook; +import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.framework.AopProxyUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.beans.factory.support.BeanDefinitionValidationException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.util.StringUtils; + +import java.util.Map; +import java.util.Objects; + + +@Configuration +public class ExtProducerResetConfiguration implements ApplicationContextAware, SmartInitializingSingleton { + private final static Logger log = LoggerFactory.getLogger(ExtProducerResetConfiguration.class); + + private ConfigurableApplicationContext applicationContext; + + private StandardEnvironment environment; + + private RocketMQProperties rocketMQProperties; + + private ObjectMapper objectMapper; + + public ExtProducerResetConfiguration(ObjectMapper rocketMQMessageObjectMapper, + StandardEnvironment environment, + RocketMQProperties rocketMQProperties) { + this.objectMapper = rocketMQMessageObjectMapper; + this.environment = environment; + this.rocketMQProperties = rocketMQProperties; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = (ConfigurableApplicationContext) applicationContext; + } + + @Override + public void afterSingletonsInstantiated() { + Map beans = this.applicationContext.getBeansWithAnnotation(ExtRocketMQTemplateConfiguration.class); + + if (Objects.nonNull(beans)) { + beans.forEach(this::registerTemplate); + } + } + + private void registerTemplate(String beanName, Object bean) { + Class clazz = AopProxyUtils.ultimateTargetClass(bean); + + if (!RocketMQTemplate.class.isAssignableFrom(bean.getClass())) { + throw new IllegalStateException(clazz + " is not instance of " + RocketMQTemplate.class.getName()); + } + + ExtRocketMQTemplateConfiguration annotation = clazz.getAnnotation(ExtRocketMQTemplateConfiguration.class); + GenericApplicationContext genericApplicationContext = (GenericApplicationContext) applicationContext; + validate(annotation, genericApplicationContext); + + DefaultMQProducer mqProducer = createProducer(annotation); + // Set instanceName same as the beanName + mqProducer.setInstanceName(beanName); + try { + mqProducer.start(); + } catch (MQClientException e) { + throw new BeanDefinitionValidationException(String.format("Failed to startup MQProducer for RocketMQTemplate {}", + beanName), e); + } + RocketMQTemplate rocketMQTemplate = (RocketMQTemplate) bean; + rocketMQTemplate.setProducer(mqProducer); + rocketMQTemplate.setObjectMapper(objectMapper); + + + log.info("Set real producer to :{} {}", beanName, annotation.value()); + } + + private DefaultMQProducer createProducer(ExtRocketMQTemplateConfiguration annotation) { + DefaultMQProducer producer = null; + + RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer(); + if (producerConfig == null) { + producerConfig = new RocketMQProperties.Producer(); + } + String nameServer = environment.resolvePlaceholders(annotation.nameServer()); + String groupName = environment.resolvePlaceholders(annotation.group()); + groupName = StringUtils.isEmpty(groupName) ? producerConfig.getGroup() : groupName; + + String ak = environment.resolvePlaceholders(annotation.accessKey()); + ak = StringUtils.isEmpty(ak) ? producerConfig.getAccessKey() : annotation.accessKey(); + String sk = environment.resolvePlaceholders(annotation.secretKey()); + sk = StringUtils.isEmpty(sk) ? producerConfig.getSecretKey() : annotation.secretKey(); + String customizedTraceTopic = environment.resolvePlaceholders(annotation.customizedTraceTopic()); + customizedTraceTopic = StringUtils.isEmpty(customizedTraceTopic) ? producerConfig.getCustomizedTraceTopic() : customizedTraceTopic; + + if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { + producer = new DefaultMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk)), + annotation.enableMsgTrace(), customizedTraceTopic); + producer.setVipChannelEnabled(false); + } else { + producer = new DefaultMQProducer(groupName, annotation.enableMsgTrace(), customizedTraceTopic); + } + + producer.setNamesrvAddr(nameServer); + producer.setSendMsgTimeout(annotation.sendMessageTimeout() == -1 ? producerConfig.getSendMessageTimeout() : annotation.sendMessageTimeout()); + producer.setRetryTimesWhenSendFailed(annotation.retryTimesWhenSendAsyncFailed() == -1 ? producerConfig.getRetryTimesWhenSendFailed() : annotation.retryTimesWhenSendAsyncFailed()); + producer.setRetryTimesWhenSendAsyncFailed(annotation.retryTimesWhenSendAsyncFailed() == -1 ? producerConfig.getRetryTimesWhenSendAsyncFailed() : annotation.retryTimesWhenSendAsyncFailed()); + producer.setMaxMessageSize(annotation.maxMessageSize() == -1 ? producerConfig.getMaxMessageSize() : annotation.maxMessageSize()); + producer.setCompressMsgBodyOverHowmuch(annotation.compressMessageBodyThreshold() == -1 ? producerConfig.getCompressMessageBodyThreshold() : annotation.compressMessageBodyThreshold()); + producer.setRetryAnotherBrokerWhenNotStoreOK(annotation.retryNextServer()); + + return producer; + } + + private void validate(ExtRocketMQTemplateConfiguration annotation, GenericApplicationContext genericApplicationContext) { + if (genericApplicationContext.isBeanNameInUse(annotation.value())) { + throw new BeanDefinitionValidationException(String.format("Bean {} has been used in Spring Application Context, " + + "please check the @ExtRocketMQTemplateConfiguration", + annotation.value())); + } + + if (rocketMQProperties.getNameServer() == null || + rocketMQProperties.getNameServer().equals(environment.resolvePlaceholders(annotation.nameServer()))) { + throw new BeanDefinitionValidationException( + "Bad annotation definition in @ExtRocketMQTemplateConfiguration, nameServer property is same with " + + "global property, please use the default RocketMQTemplate!"); + } + } +} \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java new file mode 100644 index 000000000..d25ca8d80 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/JacksonFallbackConfiguration.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.autoconfigure; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnMissingBean(ObjectMapper.class) +class JacksonFallbackConfiguration { + + @Bean + public ObjectMapper rocketMQMessageObjectMapper() { + return new ObjectMapper(); + } + +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java new file mode 100644 index 000000000..2d6cb3fde --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/ListenerContainerConfiguration.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.autoconfigure; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.rocketmq.client.AccessChannel; +import org.apache.rocketmq.spring.annotation.ConsumeMode; +import org.apache.rocketmq.spring.annotation.MessageModel; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.framework.AopProxyUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.beans.factory.support.BeanDefinitionValidationException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.util.StringUtils; + +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicLong; + + +@Configuration +public class ListenerContainerConfiguration implements ApplicationContextAware, SmartInitializingSingleton { + private final static Logger log = LoggerFactory.getLogger(ListenerContainerConfiguration.class); + + private ConfigurableApplicationContext applicationContext; + + private AtomicLong counter = new AtomicLong(0); + + private StandardEnvironment environment; + + private RocketMQProperties rocketMQProperties; + + private ObjectMapper objectMapper; + + public ListenerContainerConfiguration(ObjectMapper rocketMQMessageObjectMapper, + StandardEnvironment environment, + RocketMQProperties rocketMQProperties) { + this.objectMapper = rocketMQMessageObjectMapper; + this.environment = environment; + this.rocketMQProperties = rocketMQProperties; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = (ConfigurableApplicationContext) applicationContext; + } + + @Override + public void afterSingletonsInstantiated() { + Map beans = this.applicationContext.getBeansWithAnnotation(RocketMQMessageListener.class); + + if (Objects.nonNull(beans)) { + beans.forEach(this::registerContainer); + } + } + + private void registerContainer(String beanName, Object bean) { + Class clazz = AopProxyUtils.ultimateTargetClass(bean); + + if (!RocketMQListener.class.isAssignableFrom(bean.getClass())) { + throw new IllegalStateException(clazz + " is not instance of " + RocketMQListener.class.getName()); + } + + RocketMQMessageListener annotation = clazz.getAnnotation(RocketMQMessageListener.class); + validate(annotation); + + String containerBeanName = String.format("%s_%s", DefaultRocketMQListenerContainer.class.getName(), + counter.incrementAndGet()); + GenericApplicationContext genericApplicationContext = (GenericApplicationContext) applicationContext; + + genericApplicationContext.registerBean(containerBeanName, DefaultRocketMQListenerContainer.class, + () -> createRocketMQListenerContainer(containerBeanName, bean, annotation)); + DefaultRocketMQListenerContainer container = genericApplicationContext.getBean(containerBeanName, + DefaultRocketMQListenerContainer.class); + if (!container.isRunning()) { + try { + container.start(); + } catch (Exception e) { + log.error("Started container failed. {}", container, e); + throw new RuntimeException(e); + } + } + + log.info("Register the listener to container, listenerBeanName:{}, containerBeanName:{}", beanName, containerBeanName); + } + + private DefaultRocketMQListenerContainer createRocketMQListenerContainer(String name, Object bean, RocketMQMessageListener annotation) { + DefaultRocketMQListenerContainer container = new DefaultRocketMQListenerContainer(); + + String nameServer = environment.resolvePlaceholders(annotation.nameServer()); + nameServer = StringUtils.isEmpty(nameServer) ? rocketMQProperties.getNameServer() : nameServer; + String accessChannel = environment.resolvePlaceholders(annotation.accessChannel()); + container.setNameServer(nameServer); + if (!StringUtils.isEmpty(accessChannel)) { + container.setAccessChannel(AccessChannel.valueOf(accessChannel)); + } + container.setTopic(environment.resolvePlaceholders(annotation.topic())); + container.setConsumerGroup(environment.resolvePlaceholders(annotation.consumerGroup())); + container.setRocketMQMessageListener(annotation); + container.setRocketMQListener((RocketMQListener) bean); + container.setObjectMapper(objectMapper); + container.setName(name); // REVIEW ME, use the same clientId or multiple? + + return container; + } + + private void validate(RocketMQMessageListener annotation) { + if (annotation.consumeMode() == ConsumeMode.ORDERLY && + annotation.messageModel() == MessageModel.BROADCASTING) { + throw new BeanDefinitionValidationException( + "Bad annotation definition in @RocketMQMessageListener, messageModel BROADCASTING does not support ORDERLY message!"); + } + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java new file mode 100644 index 000000000..519636982 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfiguration.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.autoconfigure; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.rocketmq.acl.common.AclClientRPCHook; +import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.client.AccessChannel; +import org.apache.rocketmq.client.MQAdmin; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.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.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Role; +import org.springframework.core.env.Environment; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import javax.annotation.PostConstruct; + +@Configuration +@EnableConfigurationProperties(RocketMQProperties.class) +@ConditionalOnClass({ MQAdmin.class, ObjectMapper.class }) +@ConditionalOnProperty(prefix = "rocketmq", value = "name-server", matchIfMissing = true) +@Import({ JacksonFallbackConfiguration.class, ListenerContainerConfiguration.class, ExtProducerResetConfiguration.class }) +@AutoConfigureAfter(JacksonAutoConfiguration.class) +public class RocketMQAutoConfiguration { + private static final Logger log = LoggerFactory.getLogger(RocketMQAutoConfiguration.class); + + @Autowired + private Environment environment; + + @PostConstruct + public void checkProperties() { + String nameServer = environment.getProperty("rocketmq.name-server", String.class); + log.debug("rocketmq.nameServer = {}", nameServer); + if (nameServer == null) { + log.warn("The necessary spring property 'rocketmq.name-server' is not defined, all rockertmq beans creation are skipped!"); + } + } + + + @Bean + @ConditionalOnMissingBean(DefaultMQProducer.class) + @ConditionalOnProperty(prefix = "rocketmq", value = {"name-server", "producer.group"}) + public DefaultMQProducer defaultMQProducer(RocketMQProperties rocketMQProperties) { + RocketMQProperties.Producer producerConfig = rocketMQProperties.getProducer(); + String nameServer = rocketMQProperties.getNameServer(); + String groupName = producerConfig.getGroup(); + Assert.hasText(nameServer, "[rocketmq.name-server] must not be null"); + Assert.hasText(groupName, "[rocketmq.producer.group] must not be null"); + + String accessChannel = rocketMQProperties.getAccessChannel(); + + DefaultMQProducer producer; + String ak = rocketMQProperties.getProducer().getAccessKey(); + String sk = rocketMQProperties.getProducer().getSecretKey(); + if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { + producer = new DefaultMQProducer(groupName, new AclClientRPCHook(new SessionCredentials(ak, sk)), + rocketMQProperties.getProducer().isEnableMsgTrace(), + rocketMQProperties.getProducer().getCustomizedTraceTopic()); + producer.setVipChannelEnabled(false); + } else { + producer = new DefaultMQProducer(groupName, rocketMQProperties.getProducer().isEnableMsgTrace(), + rocketMQProperties.getProducer().getCustomizedTraceTopic()); + } + + producer.setNamesrvAddr(nameServer); + if (!StringUtils.isEmpty(accessChannel)) { + producer.setAccessChannel(AccessChannel.valueOf(accessChannel)); + } + producer.setSendMsgTimeout(producerConfig.getSendMessageTimeout()); + producer.setRetryTimesWhenSendFailed(producerConfig.getRetryTimesWhenSendFailed()); + producer.setRetryTimesWhenSendAsyncFailed(producerConfig.getRetryTimesWhenSendAsyncFailed()); + producer.setMaxMessageSize(producerConfig.getMaxMessageSize()); + producer.setCompressMsgBodyOverHowmuch(producerConfig.getCompressMessageBodyThreshold()); + producer.setRetryAnotherBrokerWhenNotStoreOK(producerConfig.isRetryNextServer()); + + return producer; + } + + @Bean(destroyMethod = "destroy") + @ConditionalOnBean(DefaultMQProducer.class) + @ConditionalOnMissingBean(name = RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) + public RocketMQTemplate rocketMQTemplate(DefaultMQProducer mqProducer, ObjectMapper rocketMQMessageObjectMapper) { + RocketMQTemplate rocketMQTemplate = new RocketMQTemplate(); + rocketMQTemplate.setProducer(mqProducer); + rocketMQTemplate.setObjectMapper(rocketMQMessageObjectMapper); + return rocketMQTemplate; + } + + @Bean + @ConditionalOnBean(name = RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) + @ConditionalOnMissingBean(TransactionHandlerRegistry.class) + public TransactionHandlerRegistry transactionHandlerRegistry(@Qualifier(RocketMQConfigUtils.ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME) + RocketMQTemplate template) { + return new TransactionHandlerRegistry(template); + } + + @Bean(name = RocketMQConfigUtils.ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME) + @ConditionalOnBean(TransactionHandlerRegistry.class) + @Role(BeanDefinition.ROLE_INFRASTRUCTURE) + public static RocketMQTransactionAnnotationProcessor transactionAnnotationProcessor( + TransactionHandlerRegistry transactionHandlerRegistry) { + return new RocketMQTransactionAnnotationProcessor(transactionHandlerRegistry); + } + +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java new file mode 100644 index 000000000..5fb3e3652 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/autoconfigure/RocketMQProperties.java @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.autoconfigure; + +import org.apache.rocketmq.common.MixAll; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@SuppressWarnings("WeakerAccess") +@ConfigurationProperties(prefix = "rocketmq") +public class RocketMQProperties { + + /** + * The name server for rocketMQ, formats: `host:port;host:port`. + */ + private String nameServer; + + /** + * Enum type for accesChannel, values: LOCAL, CLOUD + */ + private String accessChannel; + + private Producer producer; + + public String getNameServer() { + return nameServer; + } + + public void setNameServer(String nameServer) { + this.nameServer = nameServer; + } + + public String getAccessChannel() { + return accessChannel; + } + + public void setAccessChannel(String accessChannel) { + this.accessChannel = accessChannel; + } + + public Producer getProducer() { + return producer; + } + + public void setProducer(Producer producer) { + this.producer = producer; + } + + public static class Producer { + + /** + * Name of producer. + */ + private String group; + + /** + * Millis of send message timeout. + */ + private int sendMessageTimeout = 3000; + + /** + * Compress message body threshold, namely, message body larger than 4k will be compressed on default. + */ + private int compressMessageBodyThreshold = 1024 * 4; + + /** + * Maximum number of retry to perform internally before claiming sending failure in synchronous mode. + * This may potentially cause message duplication which is up to application developers to resolve. + */ + private int retryTimesWhenSendFailed = 2; + + /** + *

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. + */ + private int retryTimesWhenSendAsyncFailed = 2; + + /** + * Indicate whether to retry another broker on sending failure internally. + */ + private boolean retryNextServer = false; + + /** + * Maximum allowed message size in bytes. + */ + private int maxMessageSize = 1024 * 1024 * 4; + + /** + * The property of "access-key". + */ + private String accessKey; + + /** + * The property of "secret-key". + */ + private String secretKey; + + /** + * Switch flag instance for message trace. + */ + private boolean enableMsgTrace = true; + + /** + * The name value of message trace topic.If you don't config,you can use the default trace topic name. + */ + private String customizedTraceTopic = MixAll.RMQ_SYS_TRACE_TOPIC; + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + + public int getSendMessageTimeout() { + return sendMessageTimeout; + } + + public void setSendMessageTimeout(int sendMessageTimeout) { + this.sendMessageTimeout = sendMessageTimeout; + } + + public int getCompressMessageBodyThreshold() { + return compressMessageBodyThreshold; + } + + public void setCompressMessageBodyThreshold(int compressMessageBodyThreshold) { + this.compressMessageBodyThreshold = compressMessageBodyThreshold; + } + + public int getRetryTimesWhenSendFailed() { + return retryTimesWhenSendFailed; + } + + public void setRetryTimesWhenSendFailed(int retryTimesWhenSendFailed) { + this.retryTimesWhenSendFailed = retryTimesWhenSendFailed; + } + + public int getRetryTimesWhenSendAsyncFailed() { + return retryTimesWhenSendAsyncFailed; + } + + public void setRetryTimesWhenSendAsyncFailed(int retryTimesWhenSendAsyncFailed) { + this.retryTimesWhenSendAsyncFailed = retryTimesWhenSendAsyncFailed; + } + + public boolean isRetryNextServer() { + return retryNextServer; + } + + public void setRetryNextServer(boolean retryNextServer) { + this.retryNextServer = retryNextServer; + } + + public int getMaxMessageSize() { + return maxMessageSize; + } + + public void setMaxMessageSize(int maxMessageSize) { + this.maxMessageSize = maxMessageSize; + } + + 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 boolean isEnableMsgTrace() { + 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/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQConfigUtils.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQConfigUtils.java new file mode 100644 index 000000000..3e1c573de --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQConfigUtils.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.config; + +public class RocketMQConfigUtils { + /** + * The bean name of the internally managed RocketMQ transaction annotation processor. + */ + public static final String ROCKETMQ_TRANSACTION_ANNOTATION_PROCESSOR_BEAN_NAME = + "org.springframework.rocketmq.spring.starter.internalRocketMQTransAnnotationProcessor"; + + public static final String ROCKETMQ_TRANSACTION_DEFAULT_GLOBAL_NAME = + "rocketmq_transaction_default_global_name"; + + public static final String ROCKETMQ_TEMPLATE_DEFAULT_GLOBAL_NAME = + "rocketMQTemplate"; +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQTransactionAnnotationProcessor.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQTransactionAnnotationProcessor.java new file mode 100644 index 000000000..a80226504 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/RocketMQTransactionAnnotationProcessor.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.config; + +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.remoting.RPCHook; +import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; +import org.apache.rocketmq.spring.support.RocketMQUtil; +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.AnnotationUtils; + +import java.util.Collections; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RocketMQTransactionAnnotationProcessor + implements BeanPostProcessor, Ordered, ApplicationContextAware { + private final static Logger log = LoggerFactory.getLogger(RocketMQTransactionAnnotationProcessor.class); + + private ApplicationContext applicationContext; + private final Set> nonProcessedClasses = + Collections.newSetFromMap(new ConcurrentHashMap, Boolean>(64)); + + private TransactionHandlerRegistry transactionHandlerRegistry; + + public RocketMQTransactionAnnotationProcessor(TransactionHandlerRegistry transactionHandlerRegistry) { + this.transactionHandlerRegistry = transactionHandlerRegistry; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (!this.nonProcessedClasses.contains(bean.getClass())) { + Class targetClass = AopUtils.getTargetClass(bean); + RocketMQTransactionListener listener = AnnotationUtils.findAnnotation(targetClass, RocketMQTransactionListener.class); + this.nonProcessedClasses.add(bean.getClass()); + if (listener == null) { // for quick search + log.trace("No @RocketMQTransactionListener annotations found on bean type: {}", bean.getClass()); + } else { + try { + processTransactionListenerAnnotation(listener, bean); + } catch (MQClientException e) { + log.error("Failed to process annotation " + listener, e); + throw new BeanCreationException("Failed to process annotation " + listener, e); + } + } + } + + return bean; + } + + private void processTransactionListenerAnnotation(RocketMQTransactionListener listener, Object bean) + throws MQClientException { + if (transactionHandlerRegistry == null) { + throw new MQClientException("Bad usage of @RocketMQTransactionListener, " + + "the class must work with RocketMQTemplate", null); + } + if (!RocketMQLocalTransactionListener.class.isAssignableFrom(bean.getClass())) { + throw new MQClientException("Bad usage of @RocketMQTransactionListener, " + + "the class must implement interface RocketMQLocalTransactionListener", + null); + } + TransactionHandler transactionHandler = new TransactionHandler(); + transactionHandler.setBeanFactory(this.applicationContext.getAutowireCapableBeanFactory()); + transactionHandler.setName(listener.txProducerGroup()); + transactionHandler.setBeanName(bean.getClass().getName()); + transactionHandler.setListener((RocketMQLocalTransactionListener) bean); + transactionHandler.setCheckExecutor(listener.corePoolSize(), listener.maximumPoolSize(), + listener.keepAliveTime(), listener.blockingQueueSize()); + + RPCHook rpcHook = RocketMQUtil.getRPCHookByAkSk(applicationContext.getEnvironment(), + listener.accessKey(), listener.secretKey()); + + if (Objects.nonNull(rpcHook)) { + transactionHandler.setRpcHook(rpcHook); + } else { + log.debug("Access-key or secret-key not configure in " + listener + "."); + } + + transactionHandlerRegistry.registerTransactionHandler(transactionHandler); + } + + @Override + public int getOrder() { + return LOWEST_PRECEDENCE; + } + +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandler.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandler.java new file mode 100644 index 000000000..f6ce61c31 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandler.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.config; + +import org.apache.rocketmq.remoting.RPCHook; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; +import org.springframework.beans.factory.BeanFactory; + +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +class TransactionHandler { + private String name; + private String beanName; + private RocketMQLocalTransactionListener bean; + private BeanFactory beanFactory; + private ThreadPoolExecutor checkExecutor; + private RPCHook rpcHook; + + public String getBeanName() { + return beanName; + } + + public void setBeanName(String beanName) { + this.beanName = beanName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public RPCHook getRpcHook() { + return rpcHook; + } + + public void setRpcHook(RPCHook rpcHook) { + this.rpcHook = rpcHook; + } + + public BeanFactory getBeanFactory() { + return beanFactory; + } + + public void setBeanFactory(BeanFactory beanFactory) { + this.beanFactory = beanFactory; + } + + public void setListener(RocketMQLocalTransactionListener listener) { + this.bean = listener; + } + + public RocketMQLocalTransactionListener getListener() { + return this.bean; + } + + public void setCheckExecutor(int corePoolSize, int maxPoolSize, long keepAliveTime, int blockingQueueSize) { + this.checkExecutor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, + keepAliveTime, TimeUnit.MILLISECONDS, + new LinkedBlockingDeque<>(blockingQueueSize)); + } + + public ThreadPoolExecutor getCheckExecutor() { + return checkExecutor; + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java new file mode 100644 index 000000000..7307a3187 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/config/TransactionHandlerRegistry.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.config; + +import io.netty.util.internal.ConcurrentSet; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.springframework.beans.factory.DisposableBean; + +import java.util.Set; + +public class TransactionHandlerRegistry implements DisposableBean { + private RocketMQTemplate rocketMQTemplate; + + private final Set listenerContainers = new ConcurrentSet<>(); + + public TransactionHandlerRegistry(RocketMQTemplate template) { + this.rocketMQTemplate = template; + } + + @Override + public void destroy() throws Exception { + listenerContainers.clear(); + } + + public void registerTransactionHandler(TransactionHandler handler) throws MQClientException { + if (listenerContainers.contains(handler.getName())) { + throw new MQClientException(-1, + String + .format("The transaction name [%s] has been defined in TransactionListener [%s]", handler.getName(), + handler.getBeanName())); + } + listenerContainers.add(handler.getName()); + + rocketMQTemplate.createAndStartTransactionMQProducer(handler.getName(), handler.getListener(), handler.getCheckExecutor(), handler.getRpcHook()); + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQListener.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQListener.java new file mode 100644 index 000000000..bd6ceebe3 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQListener.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.core; + +public interface RocketMQListener { + void onMessage(T message); +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionListener.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionListener.java new file mode 100644 index 000000000..890aecc73 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionListener.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.spring.core; + +import org.springframework.messaging.Message; + +public interface RocketMQLocalTransactionListener { + RocketMQLocalTransactionState executeLocalTransaction(final Message msg, final Object arg); + + RocketMQLocalTransactionState checkLocalTransaction(final Message msg); +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionState.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionState.java new file mode 100644 index 000000000..91f0becb8 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQLocalTransactionState.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.core; + +public enum RocketMQLocalTransactionState { + COMMIT, + ROLLBACK, + UNKNOWN +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQPushConsumerLifecycleListener.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQPushConsumerLifecycleListener.java new file mode 100644 index 000000000..3be8cdc84 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQPushConsumerLifecycleListener.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.core; + +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.spring.support.RocketMQConsumerLifecycleListener; + +public interface RocketMQPushConsumerLifecycleListener extends RocketMQConsumerLifecycleListener { +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQTemplate.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQTemplate.java new file mode 100644 index 000000000..eab6af5e4 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/core/RocketMQTemplate.java @@ -0,0 +1,677 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.core; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.client.producer.MessageQueueSelector; +import org.apache.rocketmq.client.producer.SendCallback; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.client.producer.TransactionMQProducer; +import org.apache.rocketmq.client.producer.TransactionSendResult; +import org.apache.rocketmq.client.producer.selector.SelectMessageQueueByHash; +import org.apache.rocketmq.remoting.RPCHook; +import org.apache.rocketmq.spring.config.RocketMQConfigUtils; +import org.apache.rocketmq.spring.support.RocketMQUtil; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHeaders; +import org.springframework.messaging.MessagingException; +import org.springframework.messaging.core.AbstractMessageSendingTemplate; +import org.springframework.messaging.core.MessagePostProcessor; +import org.springframework.messaging.support.MessageBuilder; +import org.springframework.util.Assert; +import org.springframework.util.MimeTypeUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings({"WeakerAccess", "unused"}) +public class RocketMQTemplate extends AbstractMessageSendingTemplate implements InitializingBean, DisposableBean { + private static final Logger log = LoggerFactory.getLogger(RocketMQTemplate.class); + + private DefaultMQProducer producer; + + private ObjectMapper objectMapper; + + private String charset = "UTF-8"; + + private MessageQueueSelector messageQueueSelector = new SelectMessageQueueByHash(); + + private final Map cache = new ConcurrentHashMap<>(); //only put TransactionMQProducer by now!!! + + public DefaultMQProducer getProducer() { + return producer; + } + + public void setProducer(DefaultMQProducer producer) { + this.producer = producer; + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + public String getCharset() { + return charset; + } + + public void setCharset(String charset) { + this.charset = charset; + } + + public MessageQueueSelector getMessageQueueSelector() { + return messageQueueSelector; + } + + public void setMessageQueueSelector(MessageQueueSelector messageQueueSelector) { + this.messageQueueSelector = messageQueueSelector; + } + + /** + *

Send message in synchronous mode. This method returns only when the sending procedure totally completes. + * Reliable synchronous transmission is used in extensive scenes, such as important notification messages, SMS + * notification, SMS marketing system, etc..

+ *

+ * Warn: this method has internal retry-mechanism, that is, internal implementation will retry + * {@link DefaultMQProducer#getRetryTimesWhenSendFailed} times before claiming failure. As a result, multiple + * messages may potentially delivered to broker(s). It's up to the application developers to resolve potential + * duplication issue. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + * @return {@link SendResult} + */ + public SendResult syncSend(String destination, Message message) { + return syncSend(destination, message, producer.getSendMsgTimeout()); + } + + /** + * Same to {@link #syncSend(String, Message)} with send timeout specified in addition. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + * @param timeout send timeout with millis + * @return {@link SendResult} + */ + public SendResult syncSend(String destination, Message message, long timeout) { + return syncSend(destination, message, timeout, 0); + } + + /** + * syncSend batch messages in a given timeout. + * + * @param destination formats: `topicName:tags` + * @param messages Collection of {@link Message} + * @param timeout send timeout with millis + * @return {@link SendResult} + */ + public SendResult syncSend(String destination, Collection> messages, long timeout) { + if (Objects.isNull(messages) || messages.size() == 0) { + log.error("syncSend with batch failed. destination:{}, messages is empty ", destination); + throw new IllegalArgumentException("`messages` can not be empty"); + } + + try { + long now = System.currentTimeMillis(); + Collection rmqMsgs = new ArrayList<>(); + org.apache.rocketmq.common.message.Message rocketMsg; + for (Message msg:messages) { + if (Objects.isNull(msg) || Objects.isNull(msg.getPayload())) { + log.warn("Found a message empty in the batch, skip it"); + continue; + } + rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper, charset, destination, msg); + rmqMsgs.add(rocketMsg); + } + + SendResult sendResult = producer.send(rmqMsgs, timeout); + long costTime = System.currentTimeMillis() - now; + log.debug("send messages cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); + return sendResult; + } catch (Exception e) { + log.error("syncSend with batch failed. destination:{}, messages.size:{} ", destination, messages.size()); + throw new MessagingException(e.getMessage(), e); + } + } + + /** + * Same to {@link #syncSend(String, Message)} with send timeout specified in addition. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + * @param timeout send timeout with millis + * @param delayLevel level for the delay message + * @return {@link SendResult} + */ + public SendResult syncSend(String destination, Message message, long timeout, int delayLevel) { + if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { + log.error("syncSend failed. destination:{}, message is null ", destination); + throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); + } + + try { + long now = System.currentTimeMillis(); + org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper, + charset, destination, message); + if (delayLevel > 0) { + rocketMsg.setDelayTimeLevel(delayLevel); + } + SendResult sendResult = producer.send(rocketMsg, timeout); + long costTime = System.currentTimeMillis() - now; + log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); + return sendResult; + } catch (Exception e) { + log.error("syncSend failed. destination:{}, message:{} ", destination, message); + throw new MessagingException(e.getMessage(), e); + } + } + + /** + * Same to {@link #syncSend(String, Message)}. + * + * @param destination formats: `topicName:tags` + * @param payload the Object to use as payload + * @return {@link SendResult} + */ + public SendResult syncSend(String destination, Object payload) { + return syncSend(destination, payload, producer.getSendMsgTimeout()); + } + + /** + * Same to {@link #syncSend(String, Object)} with send timeout specified in addition. + * + * @param destination formats: `topicName:tags` + * @param payload the Object to use as payload + * @param timeout send timeout with millis + * @return {@link SendResult} + */ + public SendResult syncSend(String destination, Object payload, long timeout) { + Message message = this.doConvert(payload, null, null); + return syncSend(destination, message, timeout); + } + + /** + * Same to {@link #syncSend(String, Message)} with send orderly with hashKey by specified. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + * @param hashKey use this key to select queue. for example: orderId, productId ... + * @return {@link SendResult} + */ + public SendResult syncSendOrderly(String destination, Message message, String hashKey) { + return syncSendOrderly(destination, message, hashKey, producer.getSendMsgTimeout()); + } + + /** + * Same to {@link #syncSendOrderly(String, Message, String)} with send timeout specified in addition. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + * @param hashKey use this key to select queue. for example: orderId, productId ... + * @param timeout send timeout with millis + * @return {@link SendResult} + */ + public SendResult syncSendOrderly(String destination, Message message, String hashKey, long timeout) { + if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { + log.error("syncSendOrderly failed. destination:{}, message is null ", destination); + throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); + } + + try { + long now = System.currentTimeMillis(); + org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper, + charset, destination, message); + SendResult sendResult = producer.send(rocketMsg, messageQueueSelector, hashKey, timeout); + long costTime = System.currentTimeMillis() - now; + log.debug("send message cost: {} ms, msgId:{}", costTime, sendResult.getMsgId()); + return sendResult; + } catch (Exception e) { + log.error("syncSendOrderly failed. destination:{}, message:{} ", destination, message); + throw new MessagingException(e.getMessage(), e); + } + } + + /** + * Same to {@link #syncSend(String, Object)} with send orderly with hashKey by specified. + * + * @param destination formats: `topicName:tags` + * @param payload the Object to use as payload + * @param hashKey use this key to select queue. for example: orderId, productId ... + * @return {@link SendResult} + */ + public SendResult syncSendOrderly(String destination, Object payload, String hashKey) { + return syncSendOrderly(destination, payload, hashKey, producer.getSendMsgTimeout()); + } + + /** + * Same to {@link #syncSendOrderly(String, Object, String)} with send timeout specified in addition. + * + * @param destination formats: `topicName:tags` + * @param payload the Object to use as payload + * @param hashKey use this key to select queue. for example: orderId, productId ... + * @param timeout send timeout with millis + * @return {@link SendResult} + */ + public SendResult syncSendOrderly(String destination, Object payload, String hashKey, long timeout) { + Message message = this.doConvert(payload, null, null); + return syncSendOrderly(destination, message, hashKey, producer.getSendMsgTimeout()); + } + /** + * Same to {@link #asyncSend(String, Message, SendCallback)} with send timeout and delay level specified in addition. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + * @param sendCallback {@link SendCallback} + * @param timeout send timeout with millis + * @param delayLevel level for the delay message + */ + public void asyncSend(String destination, Message message, SendCallback sendCallback, long timeout, int delayLevel) { + if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { + log.error("asyncSend failed. destination:{}, message is null ", destination); + throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); + } + + try { + org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper, + charset, destination, message); + if (delayLevel > 0) { + rocketMsg.setDelayTimeLevel(delayLevel); + } + producer.send(rocketMsg, sendCallback, timeout); + } catch (Exception e) { + log.info("asyncSend failed. destination:{}, message:{} ", destination, message); + throw new MessagingException(e.getMessage(), e); + } + } + /** + * Same to {@link #asyncSend(String, Message, SendCallback)} with send timeout specified in addition. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + * @param sendCallback {@link SendCallback} + * @param timeout send timeout with millis + */ + public void asyncSend(String destination, Message message, SendCallback sendCallback, long timeout) { + asyncSend(destination,message,sendCallback,timeout,0); + } + + /** + *

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

+ *

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

+ * Similar to {@link #syncSend(String, Object)}, internal implementation would potentially retry up to {@link + * DefaultMQProducer#getRetryTimesWhenSendAsyncFailed} times before claiming sending failure, which may yield + * message duplication and application developers are the one to resolve this potential issue. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + * @param sendCallback {@link SendCallback} + */ + public void asyncSend(String destination, Message message, SendCallback sendCallback) { + asyncSend(destination, message, sendCallback, producer.getSendMsgTimeout()); + } + + /** + * Same to {@link #asyncSend(String, Object, SendCallback)} with send timeout specified in addition. + * + * @param destination formats: `topicName:tags` + * @param payload the Object to use as payload + * @param sendCallback {@link SendCallback} + * @param timeout send timeout with millis + */ + public void asyncSend(String destination, Object payload, SendCallback sendCallback, long timeout) { + Message message = this.doConvert(payload, null, null); + asyncSend(destination, message, sendCallback, timeout); + } + + /** + * Same to {@link #asyncSend(String, Message, SendCallback)}. + * + * @param destination formats: `topicName:tags` + * @param payload the Object to use as payload + * @param sendCallback {@link SendCallback} + */ + public void asyncSend(String destination, Object payload, SendCallback sendCallback) { + asyncSend(destination, payload, sendCallback, producer.getSendMsgTimeout()); + } + + /** + * Same to {@link #asyncSendOrderly(String, Message, String, SendCallback)} with send timeout specified in + * addition. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + * @param hashKey use this key to select queue. for example: orderId, productId ... + * @param sendCallback {@link SendCallback} + * @param timeout send timeout with millis + */ + public void asyncSendOrderly(String destination, Message message, String hashKey, SendCallback sendCallback, + long timeout) { + if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { + log.error("asyncSendOrderly failed. destination:{}, message is null ", destination); + throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); + } + + try { + org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper, + charset, destination, message); + producer.send(rocketMsg, messageQueueSelector, hashKey, sendCallback, timeout); + } catch (Exception e) { + log.error("asyncSendOrderly failed. destination:{}, message:{} ", destination, message); + throw new MessagingException(e.getMessage(), e); + } + } + + /** + * Same to {@link #asyncSend(String, Message, SendCallback)} with send orderly with hashKey by specified. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + * @param hashKey use this key to select queue. for example: orderId, productId ... + * @param sendCallback {@link SendCallback} + */ + public void asyncSendOrderly(String destination, Message message, String hashKey, SendCallback sendCallback) { + asyncSendOrderly(destination, message, hashKey, sendCallback, producer.getSendMsgTimeout()); + } + + /** + * Same to {@link #asyncSendOrderly(String, Message, String, SendCallback)}. + * + * @param destination formats: `topicName:tags` + * @param payload the Object to use as payload + * @param hashKey use this key to select queue. for example: orderId, productId ... + * @param sendCallback {@link SendCallback} + */ + public void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback) { + asyncSendOrderly(destination, payload, hashKey, sendCallback, producer.getSendMsgTimeout()); + } + + /** + * Same to {@link #asyncSendOrderly(String, Object, String, SendCallback)} with send timeout specified in addition. + * + * @param destination formats: `topicName:tags` + * @param payload the Object to use as payload + * @param hashKey use this key to select queue. for example: orderId, productId ... + * @param sendCallback {@link SendCallback} + * @param timeout send timeout with millis + */ + public void asyncSendOrderly(String destination, Object payload, String hashKey, SendCallback sendCallback, + long timeout) { + Message message = this.doConvert(payload, null, null); + asyncSendOrderly(destination, message, hashKey, sendCallback, timeout); + } + + /** + * Similar to UDP, this method won't wait for + * acknowledgement from broker before return. Obviously, it has maximums throughput yet potentials of message loss. + *

+ * One-way transmission is used for cases requiring moderate reliability, such as log collection. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + */ + public void sendOneWay(String destination, Message message) { + if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { + log.error("sendOneWay failed. destination:{}, message is null ", destination); + throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); + } + + try { + org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper, + charset, destination, message); + producer.sendOneway(rocketMsg); + } catch (Exception e) { + log.error("sendOneWay failed. destination:{}, message:{} ", destination, message); + throw new MessagingException(e.getMessage(), e); + } + } + + /** + * Same to {@link #sendOneWay(String, Message)} + * + * @param destination formats: `topicName:tags` + * @param payload the Object to use as payload + */ + public void sendOneWay(String destination, Object payload) { + Message message = this.doConvert(payload, null, null); + sendOneWay(destination, message); + } + + /** + * Same to {@link #sendOneWay(String, Message)} with send orderly with hashKey by specified. + * + * @param destination formats: `topicName:tags` + * @param message {@link Message} + * @param hashKey use this key to select queue. for example: orderId, productId ... + */ + public void sendOneWayOrderly(String destination, Message message, String hashKey) { + if (Objects.isNull(message) || Objects.isNull(message.getPayload())) { + log.error("sendOneWayOrderly failed. destination:{}, message is null ", destination); + throw new IllegalArgumentException("`message` and `message.payload` cannot be null"); + } + + try { + org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper, + charset, destination, message); + producer.sendOneway(rocketMsg, messageQueueSelector, hashKey); + } catch (Exception e) { + log.error("sendOneWayOrderly failed. destination:{}, message:{}", destination, message); + throw new MessagingException(e.getMessage(), e); + } + } + + /** + * Same to {@link #sendOneWayOrderly(String, Message, String)} + * + * @param destination formats: `topicName:tags` + * @param payload the Object to use as payload + */ + public void sendOneWayOrderly(String destination, Object payload, String hashKey) { + Message message = this.doConvert(payload, null, null); + sendOneWayOrderly(destination, message, hashKey); + } + + @Override + public void afterPropertiesSet() throws Exception { + if (producer != null) { + producer.start(); + } + } + + @Override + protected void doSend(String destination, Message message) { + SendResult sendResult = syncSend(destination, message); + log.debug("send message to `{}` finished. result:{}", destination, sendResult); + } + + + + @Override + protected Message doConvert(Object payload, Map headers, MessagePostProcessor postProcessor) { + String content; + if (payload instanceof String) { + content = (String) payload; + } else { + // If payload not as string, use objectMapper change it. + try { + content = objectMapper.writeValueAsString(payload); + } catch (JsonProcessingException e) { + log.error("convert payload to String failed. payload:{}", payload); + throw new RuntimeException("convert to payload to String failed.", e); + } + } + + MessageBuilder builder = MessageBuilder.withPayload(content); + if (headers != null) { + builder.copyHeaders(headers); + } + builder.setHeaderIfAbsent(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN); + + Message message = builder.build(); + if (postProcessor != null) { + message = postProcessor.postProcessMessage(message); + } + return message; + } + + @Override + public void destroy() { + if (Objects.nonNull(producer)) { + producer.shutdown(); + } + + for (Map.Entry kv : cache.entrySet()) { + if (Objects.nonNull(kv.getValue())) { + kv.getValue().shutdown(); + } + } + cache.clear(); + } + + private String getTxProducerGroupName(String name) { + return name == null ? RocketMQConfigUtils.ROCKETMQ_TRANSACTION_DEFAULT_GLOBAL_NAME : name; + } + + private TransactionMQProducer stageMQProducer(String name) throws MessagingException { + name = getTxProducerGroupName(name); + + TransactionMQProducer cachedProducer = cache.get(name); + if (cachedProducer == null) { + throw new MessagingException( + String.format("Can not found MQProducer '%s' in cache! please define @RocketMQLocalTransactionListener class or invoke createOrGetStartedTransactionMQProducer() to create it firstly", name)); + } + + return cachedProducer; + } + + /** + * Send Spring Message in Transaction + * + * @param txProducerGroup the validate txProducerGroup name, set null if using the default name + * @param destination destination formats: `topicName:tags` + * @param message message {@link Message} + * @param arg ext arg + * @return TransactionSendResult + * @throws MessagingException + */ + public TransactionSendResult sendMessageInTransaction(final String txProducerGroup, final String destination, final Message message, final Object arg) throws MessagingException { + try { + TransactionMQProducer txProducer = this.stageMQProducer(txProducerGroup); + org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper, + charset, destination, message); + return txProducer.sendMessageInTransaction(rocketMsg, arg); + } catch (MQClientException e) { + throw RocketMQUtil.convert(e); + } + } + + /** + * Remove a TransactionMQProducer from cache by manual. + *

Note: RocketMQTemplate can release all cached producers when bean destroying, it is not recommended to directly + * use this method by user. + * + * @param txProducerGroup + * @throws MessagingException + */ + public void removeTransactionMQProducer(String txProducerGroup) throws MessagingException { + txProducerGroup = getTxProducerGroupName(txProducerGroup); + if (cache.containsKey(txProducerGroup)) { + DefaultMQProducer cachedProducer = cache.get(txProducerGroup); + cachedProducer.shutdown(); + cache.remove(txProducerGroup); + } + } + + /** + * Create and start a transaction MQProducer, this new producer is cached in memory. + *

Note: This method is invoked internally when processing {@code @RocketMQLocalTransactionListener}, it is not + * recommended to directly use this method by user. + * + * @param txProducerGroup Producer (group) name, unique for each producer + * @param transactionListener TransactoinListener impl class + * @param executorService Nullable. + * @param rpcHook Nullable. + * @return true if producer is created and started; false if the named producer already exists in cache. + * @throws MessagingException + */ + public boolean createAndStartTransactionMQProducer(String txProducerGroup, + RocketMQLocalTransactionListener transactionListener, + ExecutorService executorService, RPCHook rpcHook) throws MessagingException { + txProducerGroup = getTxProducerGroupName(txProducerGroup); + if (cache.containsKey(txProducerGroup)) { + log.info(String.format("get TransactionMQProducer '%s' from cache", txProducerGroup)); + return false; + } + + TransactionMQProducer txProducer = createTransactionMQProducer(txProducerGroup, transactionListener, executorService, rpcHook); + try { + txProducer.start(); + cache.put(txProducerGroup, txProducer); + } catch (MQClientException e) { + throw RocketMQUtil.convert(e); + } + + return true; + } + + private TransactionMQProducer createTransactionMQProducer(String name, + RocketMQLocalTransactionListener transactionListener, + ExecutorService executorService, RPCHook rpcHook) { + Assert.notNull(producer, "Property 'producer' is required"); + Assert.notNull(transactionListener, "Parameter 'transactionListener' is required"); + TransactionMQProducer txProducer; + if (Objects.nonNull(rpcHook)) { + txProducer = new TransactionMQProducer(name, rpcHook); + txProducer.setVipChannelEnabled(false); + txProducer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, name)); + } else { + txProducer = new TransactionMQProducer(name); + } + txProducer.setTransactionListener(RocketMQUtil.convert(transactionListener)); + + txProducer.setNamesrvAddr(producer.getNamesrvAddr()); + if (executorService != null) { + txProducer.setExecutorService(executorService); + } + + txProducer.setSendMsgTimeout(producer.getSendMsgTimeout()); + txProducer.setRetryTimesWhenSendFailed(producer.getRetryTimesWhenSendFailed()); + txProducer.setRetryTimesWhenSendAsyncFailed(producer.getRetryTimesWhenSendAsyncFailed()); + txProducer.setMaxMessageSize(producer.getMaxMessageSize()); + txProducer.setCompressMsgBodyOverHowmuch(producer.getCompressMsgBodyOverHowmuch()); + txProducer.setRetryAnotherBrokerWhenNotStoreOK(producer.isRetryAnotherBrokerWhenNotStoreOK()); + + return txProducer; + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java new file mode 100644 index 000000000..6a730107c --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainer.java @@ -0,0 +1,494 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.support; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.rocketmq.client.AccessChannel; +import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; +import org.apache.rocketmq.client.consumer.MessageSelector; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; +import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext; +import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyStatus; +import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; +import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly; +import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely; +import org.apache.rocketmq.client.exception.MQClientException; +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.RocketMQMessageListener; +import org.apache.rocketmq.spring.annotation.SelectorType; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.apache.rocketmq.spring.core.RocketMQPushConsumerLifecycleListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.aop.framework.AopProxyUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.SmartLifecycle; +import org.springframework.util.Assert; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Objects; + +@SuppressWarnings("WeakerAccess") +public class DefaultRocketMQListenerContainer implements InitializingBean, + RocketMQListenerContainer, SmartLifecycle, ApplicationContextAware { + private final static Logger log = LoggerFactory.getLogger(DefaultRocketMQListenerContainer.class); + + private ApplicationContext applicationContext; + + /** + * The name of the DefaultRocketMQListenerContainer instance + */ + private String name; + + 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 String nameServer; + + private AccessChannel accessChannel = AccessChannel.LOCAL; + + private String consumerGroup; + + private String topic; + + private int consumeThreadMax = 64; + + private String charset = "UTF-8"; + + private ObjectMapper objectMapper; + + private RocketMQListener rocketMQListener; + + private RocketMQMessageListener rocketMQMessageListener; + + private DefaultMQPushConsumer consumer; + + private Class messageType; + + private boolean running; + + // The following properties came from @RocketMQMessageListener. + private ConsumeMode consumeMode; + private SelectorType selectorType; + private String selectorExpression; + private MessageModel messageModel; + private long consumeTimeout; + + public long getSuspendCurrentQueueTimeMillis() { + return suspendCurrentQueueTimeMillis; + } + + public void setSuspendCurrentQueueTimeMillis(long suspendCurrentQueueTimeMillis) { + this.suspendCurrentQueueTimeMillis = suspendCurrentQueueTimeMillis; + } + + public int getDelayLevelWhenNextConsume() { + return delayLevelWhenNextConsume; + } + + public void setDelayLevelWhenNextConsume(int delayLevelWhenNextConsume) { + this.delayLevelWhenNextConsume = delayLevelWhenNextConsume; + } + + public String getNameServer() { + return nameServer; + } + + public void setNameServer(String nameServer) { + this.nameServer = nameServer; + } + + public AccessChannel getAccessChannel() { + return accessChannel; + } + + public void setAccessChannel(AccessChannel accessChannel) { + this.accessChannel = accessChannel; + } + + public String getConsumerGroup() { + return consumerGroup; + } + + public void setConsumerGroup(String consumerGroup) { + this.consumerGroup = consumerGroup; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public int getConsumeThreadMax() { + return consumeThreadMax; + } + + public String getCharset() { + return charset; + } + + public void setCharset(String charset) { + this.charset = charset; + } + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + + public RocketMQListener getRocketMQListener() { + return rocketMQListener; + } + + public void setRocketMQListener(RocketMQListener rocketMQListener) { + this.rocketMQListener = rocketMQListener; + } + + public RocketMQMessageListener getRocketMQMessageListener() { + return rocketMQMessageListener; + } + + public void setRocketMQMessageListener(RocketMQMessageListener anno) { + this.rocketMQMessageListener = anno; + + this.consumeMode = anno.consumeMode(); + this.consumeThreadMax = anno.consumeThreadMax(); + this.messageModel = anno.messageModel(); + this.selectorExpression = anno.selectorExpression(); + this.selectorType = anno.selectorType(); + this.consumeTimeout = anno.consumeTimeout(); + } + + public ConsumeMode getConsumeMode() { + return consumeMode; + } + + public SelectorType getSelectorType() { + return selectorType; + } + + public String getSelectorExpression() { + return selectorExpression; + } + + public MessageModel getMessageModel() { + return messageModel; + } + + public DefaultMQPushConsumer getConsumer() { + return consumer; + } + + public void setConsumer(DefaultMQPushConsumer consumer) { + this.consumer = consumer; + } + + @Override + public void setupMessageListener(RocketMQListener rocketMQListener) { + this.rocketMQListener = rocketMQListener; + } + + @Override + public void destroy() { + this.setRunning(false); + if (Objects.nonNull(consumer)) { + consumer.shutdown(); + } + log.info("container destroyed, {}", this.toString()); + } + + @Override + public boolean isAutoStartup() { + return true; + } + + @Override + public void stop(Runnable callback) { + stop(); + callback.run(); + } + + @Override + public void start() { + if (this.isRunning()) { + throw new IllegalStateException("container already running. " + this.toString()); + } + + try { + consumer.start(); + } catch (MQClientException e) { + throw new IllegalStateException("Failed to start RocketMQ push consumer", e); + } + this.setRunning(true); + + log.info("running container: {}", this.toString()); + } + + @Override + public void stop() { + if (this.isRunning()) { + if (Objects.nonNull(consumer)) { + consumer.shutdown(); + } + setRunning(false); + } + } + + @Override + public boolean isRunning() { + return running; + } + + private void setRunning(boolean running) { + this.running = running; + } + + @Override + public int getPhase() { + // Returning Integer.MAX_VALUE only suggests that + // we will be the first bean to shutdown and last bean to start + return Integer.MAX_VALUE; + } + + + @Override + public void afterPropertiesSet() throws Exception { + initRocketMQPushConsumer(); + + this.messageType = getMessageType(); + log.debug("RocketMQ messageType: {}", messageType.getName()); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + @Override + public String toString() { + return "DefaultRocketMQListenerContainer{" + + "consumerGroup='" + consumerGroup + '\'' + + ", nameServer='" + nameServer + '\'' + + ", topic='" + topic + '\'' + + ", consumeMode=" + consumeMode + + ", selectorType=" + selectorType + + ", selectorExpression='" + selectorExpression + '\'' + + ", messageModel=" + messageModel + + '}'; + } + + public void setName(String name) { + this.name = name; + } + + public class DefaultMessageListenerConcurrently implements MessageListenerConcurrently { + + @SuppressWarnings("unchecked") + @Override + public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) { + for (MessageExt messageExt : msgs) { + log.debug("received msg: {}", messageExt); + try { + long now = System.currentTimeMillis(); + rocketMQListener.onMessage(doConvertMessage(messageExt)); + long costTime = System.currentTimeMillis() - now; + log.debug("consume {} cost: {} ms", messageExt.getMsgId(), costTime); + } catch (Exception e) { + log.warn("consume message failed. messageExt:{}", messageExt, e); + context.setDelayLevelWhenNextConsume(delayLevelWhenNextConsume); + return ConsumeConcurrentlyStatus.RECONSUME_LATER; + } + } + + return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; + } + } + + public class DefaultMessageListenerOrderly implements MessageListenerOrderly { + + @SuppressWarnings("unchecked") + @Override + public ConsumeOrderlyStatus consumeMessage(List msgs, ConsumeOrderlyContext context) { + for (MessageExt messageExt : msgs) { + log.debug("received msg: {}", messageExt); + try { + long now = System.currentTimeMillis(); + rocketMQListener.onMessage(doConvertMessage(messageExt)); + long costTime = System.currentTimeMillis() - now; + log.info("consume {} cost: {} ms", messageExt.getMsgId(), costTime); + } catch (Exception e) { + log.warn("consume message failed. messageExt:{}", messageExt, e); + context.setSuspendCurrentQueueTimeMillis(suspendCurrentQueueTimeMillis); + return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT; + } + } + + return ConsumeOrderlyStatus.SUCCESS; + } + } + + + @SuppressWarnings("unchecked") + private Object doConvertMessage(MessageExt messageExt) { + if (Objects.equals(messageType, MessageExt.class)) { + return messageExt; + } else { + String str = new String(messageExt.getBody(), Charset.forName(charset)); + if (Objects.equals(messageType, String.class)) { + return str; + } else { + // If msgType not string, use objectMapper change it. + try { + return objectMapper.readValue(str, messageType); + } catch (Exception e) { + log.info("convert failed. str:{}, msgType:{}", str, messageType); + throw new RuntimeException("cannot convert message to " + messageType, e); + } + } + } + } + + private Class getMessageType() { + Class targetClass = AopProxyUtils.ultimateTargetClass(rocketMQListener); + Type[] interfaces = targetClass.getGenericInterfaces(); + Class superclass = targetClass.getSuperclass(); + while ((Objects.isNull(interfaces) || 0 == interfaces.length) && Objects.nonNull(superclass)) { + interfaces = superclass.getGenericInterfaces(); + superclass = targetClass.getSuperclass(); + } + if (Objects.nonNull(interfaces)) { + for (Type type : interfaces) { + if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + if (Objects.equals(parameterizedType.getRawType(), RocketMQListener.class)) { + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); + if (Objects.nonNull(actualTypeArguments) && actualTypeArguments.length > 0) { + return (Class) actualTypeArguments[0]; + } else { + return Object.class; + } + } + } + } + + return Object.class; + } else { + return Object.class; + } + } + + private void initRocketMQPushConsumer() throws MQClientException { + Assert.notNull(rocketMQListener, "Property 'rocketMQListener' is required"); + Assert.notNull(consumerGroup, "Property 'consumerGroup' is required"); + Assert.notNull(nameServer, "Property 'nameServer' is required"); + Assert.notNull(topic, "Property 'topic' is required"); + + RPCHook rpcHook = RocketMQUtil.getRPCHookByAkSk(applicationContext.getEnvironment(), + this.rocketMQMessageListener.accessKey(), this.rocketMQMessageListener.secretKey()); + boolean enableMsgTrace = rocketMQMessageListener.enableMsgTrace(); + if (Objects.nonNull(rpcHook)) { + consumer = new DefaultMQPushConsumer(consumerGroup, rpcHook, new AllocateMessageQueueAveragely(), + enableMsgTrace, this.applicationContext.getEnvironment(). + resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); + consumer.setVipChannelEnabled(false); + consumer.setInstanceName(RocketMQUtil.getInstanceName(rpcHook, consumerGroup)); + } else { + log.debug("Access-key or secret-key not configure in " + this + "."); + consumer = new DefaultMQPushConsumer(consumerGroup, enableMsgTrace, + this.applicationContext.getEnvironment(). + resolveRequiredPlaceholders(this.rocketMQMessageListener.customizedTraceTopic())); + } + + String customizedNameServer = this.applicationContext.getEnvironment().resolveRequiredPlaceholders(this.rocketMQMessageListener.nameServer()); + if (customizedNameServer != null) { + consumer.setNamesrvAddr(customizedNameServer); + } else { + consumer.setNamesrvAddr(nameServer); + } + if (accessChannel != null) { + consumer.setAccessChannel(accessChannel); + } + consumer.setConsumeThreadMax(consumeThreadMax); + if (consumeThreadMax < consumer.getConsumeThreadMin()) { + consumer.setConsumeThreadMin(consumeThreadMax); + } + consumer.setConsumeTimeout(consumeTimeout); + consumer.setInstanceName(this.name); + + 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); + } + + } + +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQConsumerLifecycleListener.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQConsumerLifecycleListener.java new file mode 100644 index 000000000..8cc9b809d --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQConsumerLifecycleListener.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.support; + +public interface RocketMQConsumerLifecycleListener { + void prepareStart(final T consumer); +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQHeaders.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQHeaders.java new file mode 100644 index 000000000..7afefbdef --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQHeaders.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.spring.support; + +/** + * Represents the RocketMQ message protocol that is used during the data exchange. + */ +public class RocketMQHeaders { + public static final String PREFIX = "rocketmq_"; + public static final String KEYS = "KEYS"; + public static final String TAGS = "TAGS"; + public static final String TOPIC = "TOPIC"; + public static final String MESSAGE_ID = "MESSAGE_ID"; + public static final String BORN_TIMESTAMP = "BORN_TIMESTAMP"; + public static final String BORN_HOST = "BORN_HOST"; + public static final String FLAG = "FLAG"; + public static final String QUEUE_ID = "QUEUE_ID"; + public static final String SYS_FLAG = "SYS_FLAG"; + public static final String TRANSACTION_ID = "TRANSACTION_ID"; +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQListenerContainer.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQListenerContainer.java new file mode 100644 index 000000000..ee52de805 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQListenerContainer.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.support; + +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.DisposableBean; + +public interface RocketMQListenerContainer extends DisposableBean { + + /** + * Setup the message listener to use. Throws an {@link IllegalArgumentException} if that message listener type is + * not supported. + */ + void setupMessageListener(RocketMQListener messageListener); +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQUtil.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQUtil.java new file mode 100644 index 000000000..161fe388d --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/java/org/apache/rocketmq/spring/support/RocketMQUtil.java @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.spring.support; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.rocketmq.acl.common.AclClientRPCHook; +import org.apache.rocketmq.acl.common.SessionCredentials; +import org.apache.rocketmq.client.exception.MQClientException; +import org.apache.rocketmq.client.producer.LocalTransactionState; +import org.apache.rocketmq.client.producer.TransactionListener; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.common.message.MessageConst; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.remoting.RPCHook; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState; +import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener; +import org.springframework.core.env.Environment; +import org.springframework.messaging.MessageHeaders; +import org.springframework.messaging.MessagingException; +import org.springframework.messaging.support.MessageBuilder; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.nio.charset.Charset; +import java.util.Map; +import java.util.Objects; + +public class RocketMQUtil { + private final static Logger log = LoggerFactory.getLogger(RocketMQUtil.class); + + public static TransactionListener convert(RocketMQLocalTransactionListener listener) { + return new TransactionListener() { + @Override + public LocalTransactionState executeLocalTransaction(Message message, Object obj) { + RocketMQLocalTransactionState state = listener.executeLocalTransaction(convertToSpringMessage(message), obj); + return convertLocalTransactionState(state); + } + + @Override + public LocalTransactionState checkLocalTransaction(MessageExt messageExt) { + RocketMQLocalTransactionState state = listener.checkLocalTransaction(convertToSpringMessage(messageExt)); + return convertLocalTransactionState(state); + } + }; + } + + private static LocalTransactionState convertLocalTransactionState(RocketMQLocalTransactionState state) { + switch (state) { + case UNKNOWN: + return LocalTransactionState.UNKNOW; + case COMMIT: + return LocalTransactionState.COMMIT_MESSAGE; + case ROLLBACK: + return LocalTransactionState.ROLLBACK_MESSAGE; + } + + // Never happen + log.warn("Failed to covert enum type RocketMQLocalTransactionState.%s", state); + return LocalTransactionState.UNKNOW; + } + + public static MessagingException convert(MQClientException e) { + return new MessagingException(e.getErrorMessage(), e); + } + + public static org.springframework.messaging.Message convertToSpringMessage( + MessageExt message) { + MessageBuilder messageBuilder = + MessageBuilder.withPayload(message.getBody()). + setHeader(toRocketHeaderKey(RocketMQHeaders.KEYS), message.getKeys()). + setHeader(toRocketHeaderKey(RocketMQHeaders.TAGS), message.getTags()). + setHeader(toRocketHeaderKey(RocketMQHeaders.TOPIC), message.getTopic()). + setHeader(toRocketHeaderKey(RocketMQHeaders.MESSAGE_ID), message.getMsgId()). + setHeader(toRocketHeaderKey(RocketMQHeaders.BORN_TIMESTAMP), message.getBornTimestamp()). + setHeader(toRocketHeaderKey(RocketMQHeaders.BORN_HOST), message.getBornHostString()). + setHeader(toRocketHeaderKey(RocketMQHeaders.FLAG), message.getFlag()). + setHeader(toRocketHeaderKey(RocketMQHeaders.QUEUE_ID), message.getQueueId()). + setHeader(toRocketHeaderKey(RocketMQHeaders.SYS_FLAG), message.getSysFlag()). + setHeader(toRocketHeaderKey(RocketMQHeaders.TRANSACTION_ID), message.getTransactionId()); + addUserProperties(message.getProperties(), messageBuilder); + return messageBuilder.build(); + } + + public static String toRocketHeaderKey(String rawKey) { + return RocketMQHeaders.PREFIX + 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.springframework.messaging.Message convertToSpringMessage( + Message message) { + MessageBuilder messageBuilder = + MessageBuilder.withPayload(message.getBody()). + setHeader(toRocketHeaderKey(RocketMQHeaders.KEYS), message.getKeys()). + setHeader(toRocketHeaderKey(RocketMQHeaders.TAGS), message.getTags()). + setHeader(toRocketHeaderKey(RocketMQHeaders.TOPIC), message.getTopic()). + setHeader(toRocketHeaderKey(RocketMQHeaders.FLAG), message.getFlag()). + setHeader(toRocketHeaderKey(RocketMQHeaders.TRANSACTION_ID), message.getTransactionId()); + addUserProperties(message.getProperties(), messageBuilder); + return messageBuilder.build(); + } + + public static Message convertToRocketMessage( + ObjectMapper objectMapper, String charset, + String destination, org.springframework.messaging.Message message) { + Object payloadObj = message.getPayload(); + byte[] payloads; + + if (payloadObj instanceof String) { + payloads = ((String) payloadObj).getBytes(Charset.forName(charset)); + } else if (payloadObj instanceof byte[]) { + payloads = (byte[]) message.getPayload(); + } else { + try { + String jsonObj = objectMapper.writeValueAsString(payloadObj); + payloads = jsonObj.getBytes(Charset.forName(charset)); + } catch (Exception e) { + throw new RuntimeException("convert to RocketMQ message failed.", e); + } + } + + String[] tempArr = destination.split(":", 2); + String topic = tempArr[0]; + String tags = ""; + if (tempArr.length > 1) { + tags = tempArr[1]; + } + + Message rocketMsg = new Message(topic, tags, payloads); + + MessageHeaders headers = message.getHeaders(); + if (Objects.nonNull(headers) && !headers.isEmpty()) { + Object keys = headers.get(RocketMQHeaders.KEYS); + if (!StringUtils.isEmpty(keys)) { // if headers has 'KEYS', set rocketMQ message key + rocketMsg.setKeys(keys.toString()); + } + + Object flagObj = headers.getOrDefault("FLAG", "0"); + int flag = 0; + try { + flag = Integer.parseInt(flagObj.toString()); + } catch (NumberFormatException e) { + // Ignore it + log.info("flag must be integer, flagObj:{}", flagObj); + } + rocketMsg.setFlag(flag); + + Object waitStoreMsgOkObj = headers.getOrDefault("WAIT_STORE_MSG_OK", "true"); + boolean waitStoreMsgOK = Boolean.TRUE.equals(waitStoreMsgOkObj); + rocketMsg.setWaitStoreMsgOK(waitStoreMsgOK); + + headers.entrySet().stream() + .filter(entry -> !Objects.equals(entry.getKey(), "FLAG") + && !Objects.equals(entry.getKey(), "WAIT_STORE_MSG_OK")) // exclude "FLAG", "WAIT_STORE_MSG_OK" + .forEach(entry -> { + if (!MessageConst.STRING_HASH_SET.contains(entry.getKey())) { + rocketMsg.putUserProperty(entry.getKey(), String.valueOf(entry.getValue())); + } + }); + + } + + return rocketMsg; + } + + public static RPCHook getRPCHookByAkSk(Environment env, String accessKeyOrExpr, String secretKeyOrExpr) { + String ak, sk; + try { + ak = env.resolveRequiredPlaceholders(accessKeyOrExpr); + sk = env.resolveRequiredPlaceholders(secretKeyOrExpr); + } catch (Exception e) { + // Ignore it + ak = null; + sk = null; + } + if (!StringUtils.isEmpty(ak) && !StringUtils.isEmpty(sk)) { + return new AclClientRPCHook(new SessionCredentials(ak, sk)); + } + return null; + } + + public static String getInstanceName(RPCHook rpcHook, String identify) { + String separator = "|"; + StringBuilder instanceName = new StringBuilder(); + SessionCredentials sessionCredentials = ((AclClientRPCHook) rpcHook).getSessionCredentials(); + instanceName.append(sessionCredentials.getAccessKey()) + .append(separator).append(sessionCredentials.getSecretKey()) + .append(separator).append(identify); + return instanceName.toString(); + } +} diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/resources/META-INF/spring.factories b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..d97635486 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.apache.rocketmq.spring.autoconfigure.RocketMQAutoConfiguration \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java new file mode 100644 index 000000000..528e91612 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/autoconfigure/RocketMQAutoConfigurationTest.java @@ -0,0 +1,221 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.rocketmq.spring.autoconfigure; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.rocketmq.client.producer.DefaultMQProducer; +import org.apache.rocketmq.spring.annotation.ExtRocketMQTemplateConfiguration; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.support.BeanDefinitionValidationException; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.assertj.AssertableApplicationContext; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.boot.test.context.runner.ContextConsumer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +public class RocketMQAutoConfigurationTest { + private ApplicationContextRunner runner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(RocketMQAutoConfiguration.class)); + + + @Test(expected = NoSuchBeanDefinitionException.class) + public void testDefaultMQProducerNotCreatedByDefault() { + // You will see the WARN log message about missing rocketmq.name-server spring property when running this test case. + runner.run(context -> context.getBean(DefaultMQProducer.class)); + } + + + @Test + public void testDefaultMQProducerWithRelaxPropertyName() { + runner.withPropertyValues("rocketmq.nameServer=127.0.0.1:9876", + "rocketmq.producer.group=spring_rocketmq", + "rocketmq.accessChannel=LOCAL"). + run((context) -> { + assertThat(context).hasSingleBean(DefaultMQProducer.class); + assertThat(context).hasSingleBean(RocketMQProperties.class); + }); + + } + + @Test + public void testBadAccessChannelProperty() { + runner.withPropertyValues("rocketmq.nameServer=127.0.0.1:9876", + "rocketmq.producer.group=spring_rocketmq", + "rocketmq.accessChannel=LOCAL123"). + run((context) -> { + //Should throw exception for bad accessChannel property + assertThat(context).getFailure(); + }); + } + + @Test + public void testDefaultMQProducer() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876", + "rocketmq.producer.group=spring_rocketmq"). + run((context) -> { + assertThat(context).hasSingleBean(DefaultMQProducer.class); + }); + + } + + @Test + public void testRocketMQListenerContainer() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). + withUserConfiguration(TestConfig.class). + run((context) -> { + // No producer on consume side + assertThat(context).doesNotHaveBean(DefaultMQProducer.class); + // Auto-create consume container if existing Bean annotated with @RocketMQMessageListener + assertThat(context).hasBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1"); + assertThat(context).hasBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_2"); + assertThat(context).getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1"). + hasFieldOrPropertyWithValue("nameServer", "127.0.0.1:9876"); + assertThat(context).getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_2"). + hasFieldOrPropertyWithValue("nameServer", "127.0.1.1:9876"); + }); + + } + + @Test + public void testRocketMQListenerWithCustomObjectMapper() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). + withUserConfiguration(TestConfig.class, CustomObjectMapperConfig.class). + run((context) -> { + assertThat(context.getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1", + DefaultRocketMQListenerContainer.class).getObjectMapper()) + .isSameAs(context.getBean(CustomObjectMapperConfig.class).testObjectMapper()); + }); + } + + @Test + public void testRocketMQListenerWithSeveralObjectMappers() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). + withUserConfiguration(TestConfig.class, CustomObjectMappersConfig.class). + run((context) -> { + assertThat(context.getBean("org.apache.rocketmq.spring.support.DefaultRocketMQListenerContainer_1", + DefaultRocketMQListenerContainer.class).getObjectMapper()) + .isSameAs(context.getBean(CustomObjectMappersConfig.class).rocketMQMessageObjectMapper()); + }); + } + + + @Test + public void testExtRocketMQTemplate() { + runner.withPropertyValues("rocketmq.name-server=127.0.0.1:9876"). + withUserConfiguration(ExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). + run(new ContextConsumer() { + @Override + public void accept(AssertableApplicationContext context) throws Throwable { + Throwable th = context.getStartupFailure(); + System.out.printf("th==" + th + "\n"); + Assert.assertTrue(th instanceof BeanDefinitionValidationException); + } + }); + + runner.withPropertyValues("rocketmq.name-server=127.0.1.1:9876"). + withUserConfiguration(ExtRocketMQTemplateConfig.class, CustomObjectMappersConfig.class). + run((context) -> { + // No producer on consume side + assertThat(context).getBean("extRocketMQTemplate").hasFieldOrProperty("producer"); + // Auto-create consume container if existing Bean annotated with @RocketMQMessageListener + }); + } + + @Configuration + static class TestConfig { + + @Bean + public Object consumeListener() { + return new MyMessageListener(); + } + + @Bean + public Object consumeListener1() { + return new MyMessageListener1(); + } + + } + + @Configuration + static class CustomObjectMapperConfig { + + @Bean + public ObjectMapper testObjectMapper() { + return new ObjectMapper(); + } + + } + + @Configuration + static class CustomObjectMappersConfig { + + @Bean + public ObjectMapper testObjectMapper() { + return new ObjectMapper(); + } + + @Bean + public ObjectMapper rocketMQMessageObjectMapper() { + return new ObjectMapper(); + } + + } + + @RocketMQMessageListener(consumerGroup = "abc", topic = "test") + static class MyMessageListener implements RocketMQListener { + + @Override + public void onMessage(Object message) { + + } + } + + @RocketMQMessageListener(nameServer = "127.0.1.1:9876", consumerGroup = "abc1", topic = "test") + static class MyMessageListener1 implements RocketMQListener { + + @Override + public void onMessage(Object message) { + + } + } + + @Configuration + static class ExtRocketMQTemplateConfig { + + @Bean + public RocketMQTemplate extRocketMQTemplate() { + return new MyExtRocketMQTemplate(); + } + + } + + @ExtRocketMQTemplateConfiguration(group = "test", nameServer = "127.0.0.1:9876") + static class MyExtRocketMQTemplate extends RocketMQTemplate { + + } +} + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainerTest.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainerTest.java new file mode 100644 index 000000000..ea85b98d9 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/DefaultRocketMQListenerContainerTest.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.spring.support; + +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.junit.Test; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import static org.assertj.core.api.Assertions.assertThat; + +public class DefaultRocketMQListenerContainerTest { + @Test + public void testGetMessageType() throws Exception { + DefaultRocketMQListenerContainer listenerContainer = new DefaultRocketMQListenerContainer(); + Method getMessageType = DefaultRocketMQListenerContainer.class.getDeclaredMethod("getMessageType"); + getMessageType.setAccessible(true); + + listenerContainer.setRocketMQListener(new RocketMQListener() { + @Override + public void onMessage(String message) { + } + }); + Class result = (Class)getMessageType.invoke(listenerContainer); + assertThat(result.getName().equals(String.class.getName())); + + listenerContainer.setRocketMQListener(new RocketMQListener() { + @Override + public void onMessage(MessageExt message) { + } + }); + result = (Class)getMessageType.invoke(listenerContainer); + assertThat(result.getName().equals(MessageExt.class.getName())); + } +} + + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/RocketMQUtilTest.java b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/RocketMQUtilTest.java new file mode 100644 index 000000000..3704802d9 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/rocketmq-spring-boot/src/test/java/org/apache/rocketmq/spring/support/RocketMQUtilTest.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.rocketmq.spring.support; + +import java.util.Arrays; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Test; +import org.springframework.messaging.Message; +import org.springframework.messaging.support.MessageBuilder; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class RocketMQUtilTest { + + private ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void testMessageBuilder() { + Message msg = MessageBuilder.withPayload("test"). + setHeader("A", "test1"). + setHeader("B", "test2"). + build(); + System.out.printf("header size=%d %s %n", msg.getHeaders().size(), msg.getHeaders().toString()); + assertTrue(msg.getHeaders().get("A") != null); + assertTrue(msg.getHeaders().get("B") != null); + } + + @Test + public void testPayload() { + String charset = "UTF-8"; + String destination = "test-topic"; + Message msgWithStringPayload = MessageBuilder.withPayload("test").build(); + org.apache.rocketmq.common.message.Message rocketMsg1 = RocketMQUtil.convertToRocketMessage(objectMapper, + charset, destination, msgWithStringPayload); + + Message msgWithBytePayload = MessageBuilder.withPayload("test".getBytes()).build(); + org.apache.rocketmq.common.message.Message rocketMsg2 = RocketMQUtil.convertToRocketMessage(objectMapper, + charset, destination, msgWithBytePayload); + + assertTrue(Arrays.equals(((String)msgWithStringPayload.getPayload()).getBytes(), rocketMsg1.getBody())); + assertTrue(Arrays.equals((byte[])msgWithBytePayload.getPayload(), rocketMsg2.getBody())); + } + + @Test + public void testHeaderConvertToRMQMsg() { + Message msgWithStringPayload = MessageBuilder.withPayload("test body") + .setHeader("test", 1) + .setHeader(RocketMQHeaders.TAGS, "tags") + .setHeader(RocketMQHeaders.KEYS, "my_keys") + .build(); + org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper, + "UTF-8", "test-topic", msgWithStringPayload); + assertEquals(String.valueOf("1"), rocketMsg.getProperty("test")); + assertNull(rocketMsg.getProperty(RocketMQHeaders.TAGS)); + assertEquals("my_keys", rocketMsg.getProperty(RocketMQHeaders.KEYS)); + } + + @Test + public void testHeaderConvertToSpringMsg() { + org.apache.rocketmq.common.message.Message rmqMsg = new org.apache.rocketmq.common.message.Message(); + rmqMsg.setBody("test body".getBytes()); + rmqMsg.setTopic("test-topic"); + rmqMsg.putUserProperty("test", "1"); + rmqMsg.setTags("tags"); + Message springMsg = RocketMQUtil.convertToSpringMessage(rmqMsg); + assertEquals(String.valueOf("1"), springMsg.getHeaders().get("test")); + assertEquals("tags", springMsg.getHeaders().get(RocketMQHeaders.PREFIX + RocketMQHeaders.TAGS)); + + org.apache.rocketmq.common.message.Message rocketMsg = RocketMQUtil.convertToRocketMessage(objectMapper, + "UTF-8", "test-topic", springMsg); + assertEquals(String.valueOf("1"), rocketMsg.getProperty("test")); + assertEquals(String.valueOf("tags"), rocketMsg.getProperty(RocketMQHeaders.PREFIX + RocketMQHeaders.TAGS)); + assertNull(rocketMsg.getTags()); + } + +} \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/copyright/Apache.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/copyright/Apache.xml new file mode 100644 index 000000000..e3e3dec30 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/copyright/Apache.xml @@ -0,0 +1,23 @@ + + + + + + \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/copyright/profiles_settings.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/copyright/profiles_settings.xml new file mode 100644 index 000000000..747c7e2bf --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/copyright/profiles_settings.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/rmq_checkstyle.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/rmq_checkstyle.xml new file mode 100644 index 000000000..2e9658f4f --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/rmq_checkstyle.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/rmq_codeStyle.xml b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/rmq_codeStyle.xml new file mode 100644 index 000000000..9db075e36 --- /dev/null +++ b/esua-epdc/epdc-commons/rocketmq-spring-rocketmq-spring-all/style/rmq_codeStyle.xml @@ -0,0 +1,157 @@ + + + + + + + \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-client/src/main/java/com/elink/esua/epdc/dto/consult/GridOperatorInfoDTO.java b/esua-epdc/epdc-module/epdc-custom/epdc-custom-client/src/main/java/com/elink/esua/epdc/dto/consult/GridOperatorInfoDTO.java index ed063ccbd..b6d6e9b01 100755 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-client/src/main/java/com/elink/esua/epdc/dto/consult/GridOperatorInfoDTO.java +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-client/src/main/java/com/elink/esua/epdc/dto/consult/GridOperatorInfoDTO.java @@ -108,6 +108,8 @@ public class GridOperatorInfoDTO implements Serializable { */ private String[] allDeptIds; + private String allDeptIdsStr; + /** * 所有部门名称 */ diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/pom.xml b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/pom.xml index 83037907b..d574ff518 100644 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/pom.xml +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/pom.xml @@ -86,6 +86,12 @@ epdc-commons-tools-wx-ma ${project.version} + + + org.apache.rocketmq + rocketmq-spring-boot-starter + 2.0.3 + @@ -175,6 +181,9 @@ false 47.104.224.45:8848 + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup @@ -208,6 +217,9 @@ true 47.104.224.45:8848 + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/consult/dao/GridOperatorInfoDao.java b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/consult/dao/GridOperatorInfoDao.java index f9d5120cb..0a11bdaa4 100755 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/consult/dao/GridOperatorInfoDao.java +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/consult/dao/GridOperatorInfoDao.java @@ -56,4 +56,15 @@ public interface GridOperatorInfoDao extends BaseDao { * @date 2020/3/3 9:57 */ List selectListGridOperator(GridOperatorListFormDTO formDto); + + /** + * + * 查询需要修改的组织机构信息 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 14:09 + */ + List selectListOfOrganizationInfo(String deptId); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/consult/service/GridOperatorInfoService.java b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/consult/service/GridOperatorInfoService.java index 5d79c55b8..6835f3f59 100755 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/consult/service/GridOperatorInfoService.java +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/consult/service/GridOperatorInfoService.java @@ -25,6 +25,7 @@ import com.elink.esua.epdc.dto.enterprise.EnterpriseInfoDTO; import com.elink.esua.epdc.dto.consult.form.GridOperatorListFormDTO; import com.elink.esua.epdc.dto.consult.result.GridOperatorListResultDTO; import com.elink.esua.epdc.modules.consult.entity.GridOperatorInfoEntity; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import java.util.List; import java.util.Map; @@ -132,4 +133,15 @@ public interface GridOperatorInfoService extends BaseService gridList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != gridList && gridList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, gridList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, gridList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 14:12 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List gridList) { + List entities = new ArrayList<>(); + for (GridOperatorInfoDTO grid: gridList) { + GridOperatorInfoEntity entity = new GridOperatorInfoEntity(); + if (StringUtils.isNotEmpty(grid.getParentDeptIds()) && StringUtils.isNotEmpty(grid.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(grid.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(grid.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(grid.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(grid.getAllDeptIdsStr()) && StringUtils.isNotEmpty(grid.getAllDeptNames())) { + List allDeptIds = Arrays.asList(grid.getAllDeptIdsStr().split(",")); + List allDeptNames = Arrays.asList(grid.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(grid.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } + } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/dao/EnterpriseInfoDao.java b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/dao/EnterpriseInfoDao.java index 96f0d13a0..41b9e86d4 100644 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/dao/EnterpriseInfoDao.java +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/dao/EnterpriseInfoDao.java @@ -62,4 +62,15 @@ public interface EnterpriseInfoDao extends BaseDao { * @Param [params] **/ List selectEnterpriseInfoPageFromPc(Map params); + + /** + * + * 查询需要修改组织机构信息的企业信息 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 13:52 + */ + List selectListOfOrganizationInfo(String deptId); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/service/EnterpriseInfoService.java b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/service/EnterpriseInfoService.java index 92afc295d..3ca769318 100644 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/service/EnterpriseInfoService.java +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/service/EnterpriseInfoService.java @@ -25,6 +25,7 @@ import com.elink.esua.epdc.dto.enterprise.form.EnterpriseInfoFormDTO; import com.elink.esua.epdc.dto.enterprise.result.EnterpriseInfoResultDTO; import com.elink.esua.epdc.dto.form.CompleteRequisiteInfoDTO; import com.elink.esua.epdc.modules.enterprise.entity.EnterpriseInfoEntity; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import org.apache.ibatis.annotations.Param; import java.util.List; @@ -143,4 +144,15 @@ public interface EnterpriseInfoService extends BaseService * @Param [params] **/ List listExport(Map params); + + /** + * + * 企业信息表修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/service/impl/EnterpriseInfoServiceImpl.java b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/service/impl/EnterpriseInfoServiceImpl.java index 68a02e338..0dc129616 100644 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/service/impl/EnterpriseInfoServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/enterprise/service/impl/EnterpriseInfoServiceImpl.java @@ -39,12 +39,14 @@ import com.elink.esua.epdc.modules.enterprise.entity.EnterpriseInfoEntity; import com.elink.esua.epdc.modules.enterprise.service.EnterpriseInfoService; import com.elink.esua.epdc.modules.feign.AdminFeignClient; import com.elink.esua.epdc.modules.feign.UserFeignClient; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import io.seata.spring.annotation.GlobalTransactional; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -185,4 +187,58 @@ public class EnterpriseInfoServiceImpl extends BaseServiceImpl listExport(Map params) { return baseDao.selectEnterpriseInfoPageFromPc(params); } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyOrganizationInfo(OrganizationModifyDTO dto) { + // 查询需要修改组织机构信息企业 + List enterpriseList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != enterpriseList && enterpriseList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, enterpriseList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, eventsList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 13:54 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List enterpriseList) { + List entities = new ArrayList<>(); + for (EnterpriseInfoDTO enterprise: enterpriseList) { + EnterpriseInfoEntity entity = new EnterpriseInfoEntity(); + if (StringUtils.isNotEmpty(enterprise.getParentDeptIds()) && StringUtils.isNotEmpty(enterprise.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(enterprise.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(enterprise.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(enterprise.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(enterprise.getAllDeptIds()) && StringUtils.isNotEmpty(enterprise.getAllDeptNames())) { + List allDeptIds = Arrays.asList(enterprise.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(enterprise.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(enterprise.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/dao/EvaluateDeptDao.java b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/dao/EvaluateDeptDao.java index 0383af64b..bc7c8a52a 100644 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/dao/EvaluateDeptDao.java +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/dao/EvaluateDeptDao.java @@ -50,4 +50,26 @@ public interface EvaluateDeptDao extends BaseDao { List getEvaluateDeptCount(Map params); void deptUpdate(); + + /** + * + * 查询需要修改组织机构信息事件 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 13:58 + */ + List selectListOfOrganizationInfo(String deptId); + + /** + * + * 更新部门名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateDeptNameByDeptId(String newDeptName, Long deptId); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/service/EvaluateDeptService.java b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/service/EvaluateDeptService.java index 89ba0f12f..87d836ec5 100644 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/service/EvaluateDeptService.java +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/service/EvaluateDeptService.java @@ -22,6 +22,7 @@ import com.elink.esua.epdc.commons.tools.page.PageData; import com.elink.esua.epdc.dto.evaluate.result.EvaluateDeptCountResultDTO; import com.elink.esua.epdc.dto.evaluate.EvaluateDeptDTO; import com.elink.esua.epdc.modules.evaluate.entity.EvaluateDeptEntity; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import java.util.List; import java.util.Map; @@ -109,4 +110,15 @@ public interface EvaluateDeptService extends BaseService { * @date 2020-02-05 */ void delete(String[] ids); + + /** + * + * 评价部门表修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/service/impl/EvaluateDeptServiceImpl.java b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/service/impl/EvaluateDeptServiceImpl.java index 9698de34f..dba8f20f8 100644 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/service/impl/EvaluateDeptServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/modules/evaluate/service/impl/EvaluateDeptServiceImpl.java @@ -29,11 +29,13 @@ import com.elink.esua.epdc.modules.evaluate.dao.EvaluateDeptDao; import com.elink.esua.epdc.modules.evaluate.entity.EvaluateDeptEntity; import com.elink.esua.epdc.modules.evaluate.redis.EvaluateDeptRedis; import com.elink.esua.epdc.modules.evaluate.service.EvaluateDeptService; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -131,4 +133,61 @@ public class EvaluateDeptServiceImpl extends BaseServiceImpl evaluateList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != evaluateList && evaluateList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, evaluateList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + + // 更新网格名称 + baseDao.updateDeptNameByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, eventsList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 14:02 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List evaluateList) { + List entities = new ArrayList<>(); + for (EvaluateDeptDTO evaluate: evaluateList) { + EvaluateDeptEntity entity = new EvaluateDeptEntity(); + if (StringUtils.isNotEmpty(evaluate.getParentDeptIds()) && StringUtils.isNotEmpty(evaluate.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(evaluate.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(evaluate.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(evaluate.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(evaluate.getAllDeptIds()) && StringUtils.isNotEmpty(evaluate.getAllDeptNames())) { + List allDeptIds = Arrays.asList(evaluate.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(evaluate.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(evaluate.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } + } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/rocketmq/consumer/OrganizationModifyConsumer.java b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/rocketmq/consumer/OrganizationModifyConsumer.java new file mode 100644 index 000000000..989bb205f --- /dev/null +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/rocketmq/consumer/OrganizationModifyConsumer.java @@ -0,0 +1,59 @@ +package com.elink.esua.epdc.rocketmq.consumer; + +import com.alibaba.fastjson.JSONObject; +import com.elink.esua.epdc.commons.tools.constant.RocketMqConstant; +import com.elink.esua.epdc.modules.consult.service.GridOperatorInfoService; +import com.elink.esua.epdc.modules.enterprise.service.EnterpriseInfoService; +import com.elink.esua.epdc.modules.evaluate.service.EvaluateDeptService; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.MessageModel; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.xml.ws.Action; + +/** + * + * 组织机构信息修改-监听MQ消息 + * + * @Author:liuchuang + * @Date:2020/3/7 13:38 + */ +@Slf4j +@Component +@RocketMQMessageListener(topic = RocketMqConstant.MQ_TOPIC_ORGANIZATION, consumerGroup = "${rocketmq.consumer.group}", messageModel = MessageModel.BROADCASTING) +public class OrganizationModifyConsumer implements RocketMQListener { + + @Autowired + private EnterpriseInfoService enterpriseInfoService; + + @Autowired + private EvaluateDeptService evaluateDeptService; + + @Autowired + private GridOperatorInfoService gridOperatorInfoService; + + @Override + public void onMessage(MessageExt messageExt) { + log.info("EPDC-CUSTOM-SERVER消费消息START:{topic:{}, msgId:{}}", RocketMqConstant.MQ_TOPIC_ORGANIZATION, messageExt.getMsgId()); + try { + String charset = "UTF-8"; + String body = new String(messageExt.getBody(), charset); + OrganizationModifyDTO dto = JSONObject.parseObject(body, OrganizationModifyDTO.class); + // 企业信息表修改组织机构信息 + enterpriseInfoService.modifyOrganizationInfo(dto); + // 评价部门表修改组织机构信息 + evaluateDeptService.modifyOrganizationInfo(dto); + // 网格员信息表修改组织机构信息 + gridOperatorInfoService.modifyOrganizationInfo(dto); + log.info("EPDC-CUSTOM-SERVER消费消息END:{topic:{}, msgId:{}, body:{}}", RocketMqConstant.MQ_TOPIC_ORGANIZATION, messageExt.getMsgId(), body); + } catch (Exception e) { + log.info("EPDC-CUSTOM-SERVER消费消息失败:msgId:{}", messageExt.getMsgId()); + e.printStackTrace(); + } + } +} diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java new file mode 100644 index 000000000..2e1b5b7a5 --- /dev/null +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java @@ -0,0 +1,37 @@ +package com.elink.esua.epdc.rocketmq.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * + * 组织机构信息修改-接收MQ消息DTO + * + * @Author:liuchuang + * @Date:2020/3/6 22:34 + */ +@Data +public class OrganizationModifyDTO implements Serializable { + + private static final long serialVersionUID = -6534846437298229554L; + /** + * 部门ID + */ + private Long deptId; + + /** + * 旧部门名称 + */ + private String oldDeptName; + + /** + * 新部门名称 + */ + private String newDeptName; + + /** + * 部门类型 + */ + private String typeKey; +} diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/application.yml b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/application.yml index c27e7a5c2..9018540c8 100644 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/application.yml +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/application.yml @@ -90,4 +90,9 @@ wx: # 工作端的appId work: @work.wx.ma.appId@ # 数据分析端的appId - analysis: @analysis.wx.ma.appId@ \ No newline at end of file + analysis: @analysis.wx.ma.appId@ + +rocketmq: + name-server: @rocketmq.name.server@ + consumer: + group: @rocketmq.consumer.group@ \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/consult/GridOperatorInfoDao.xml b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/consult/GridOperatorInfoDao.xml index b82b9ee24..590c2370d 100755 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/consult/GridOperatorInfoDao.xml +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/consult/GridOperatorInfoDao.xml @@ -67,4 +67,17 @@ LIMIT #{pageIndex}, #{pageSize} + + \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/enterprise/EnterpriseInfoDao.xml b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/enterprise/EnterpriseInfoDao.xml index eec3eef9f..487ec97a3 100644 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/enterprise/EnterpriseInfoDao.xml +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/enterprise/EnterpriseInfoDao.xml @@ -70,4 +70,17 @@ ORDER BY CREATED_TIME DESC + + \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/evaluate/EvaluateDeptDao.xml b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/evaluate/EvaluateDeptDao.xml index 4f546a014..134c96939 100644 --- a/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/evaluate/EvaluateDeptDao.xml +++ b/esua-epdc/epdc-module/epdc-custom/epdc-custom-server/src/main/resources/mapper/evaluate/EvaluateDeptDao.xml @@ -249,4 +249,21 @@ ) dept + + + + UPDATE epdc_evaluate_dept SET DEPT_NAME = #{newDeptName}, UPDATED_TIME = NOW() WHERE DEPT_ID = #{deptId} + + \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/events/EpdcEventsDTO.java b/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/events/EpdcEventsDTO.java index 4f5899fd8..13a104dbe 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/events/EpdcEventsDTO.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/events/EpdcEventsDTO.java @@ -48,5 +48,26 @@ public class EpdcEventsDTO implements Serializable { * 提交时间 */ private Date createdTime; + /** + * 父所有部门ID + */ + private String parentDeptIds; + /** + * 父所有部门名称 + */ + private String parentDeptNames; + /** + * 所有部门ID + */ + private String allDeptIds; + /** + * 所有部门名称 + */ + private String allDeptNames; + + /** + * 分类全称 + */ + private String categoryFullName; } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/events/form/GroupFormDTO.java b/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/events/form/GroupFormDTO.java new file mode 100644 index 000000000..3b2b75fc3 --- /dev/null +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/events/form/GroupFormDTO.java @@ -0,0 +1,24 @@ +package com.elink.esua.epdc.dto.events.form; + +import lombok.Data; + +import java.io.Serializable; + +/** + * @Author:liuchuang + * @Date:2020/3/7 12:46 + */ +@Data +public class GroupFormDTO implements Serializable { + private static final long serialVersionUID = 5915096900970194933L; + + /** + * 社群ID + */ + private String id; + + /** + * 社群名称 + */ + private String groupName; +} diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/issue/IssueDTO.java b/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/issue/IssueDTO.java index b42f1b3d4..0b203bc7a 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/issue/IssueDTO.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/issue/IssueDTO.java @@ -183,4 +183,26 @@ public class IssueDTO implements Serializable { */ private String issueCode; + /** + * 父所有部门ID + */ + private String parentDeptIds; + /** + * 父所有部门名称 + */ + private String parentDeptNames; + /** + * 所有部门ID + */ + private String allDeptIds; + /** + * 所有部门名称 + */ + private String allDeptNames; + + /** + * 分类全称 + */ + private String categoryFullName; + } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/item/ItemDTO.java b/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/item/ItemDTO.java index 8e6ce9ba5..ebe00bdc5 100755 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/item/ItemDTO.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-client/src/main/java/com/elink/esua/epdc/dto/item/ItemDTO.java @@ -200,4 +200,26 @@ public class ItemDTO implements Serializable { */ private String itemCode; + /** + * 父所有部门ID + */ + private String parentDeptIds; + /** + * 父所有部门名称 + */ + private String parentDeptNames; + /** + * 所有部门ID + */ + private String allDeptIds; + /** + * 所有部门名称 + */ + private String allDeptNames; + + /** + * 分类全称 + */ + private String categoryFullName; + } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/pom.xml b/esua-epdc/epdc-module/epdc-events/epdc-events-server/pom.xml index e3afbcc25..fe249af11 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/pom.xml +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/pom.xml @@ -75,6 +75,12 @@ 1.0.0 compile + + + org.apache.rocketmq + rocketmq-spring-boot-starter + 2.0.3 + @@ -167,6 +173,11 @@ wx9b6102a8ee5add65 394f47d4e08fc0fd629231d3f68a34dc + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup + categoryGroup + categoryGroup @@ -206,6 +217,11 @@ wx9b6102a8ee5add65 394f47d4e08fc0fd629231d3f68a34dc + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup + categoryGroup + categoryGroup diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/category/service/impl/CategoryServiceImpl.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/category/service/impl/CategoryServiceImpl.java index 8d1c455a7..1457a189c 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/category/service/impl/CategoryServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/category/service/impl/CategoryServiceImpl.java @@ -23,6 +23,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.elink.esua.epdc.commons.mybatis.service.impl.BaseServiceImpl; import com.elink.esua.epdc.commons.tools.constant.Constant; import com.elink.esua.epdc.commons.tools.constant.NumConstant; +import com.elink.esua.epdc.commons.tools.constant.RocketMqConstant; import com.elink.esua.epdc.commons.tools.exception.ErrorCode; import com.elink.esua.epdc.commons.tools.exception.RenException; import com.elink.esua.epdc.commons.tools.redis.RedisKeys; @@ -40,6 +41,8 @@ import com.elink.esua.epdc.modules.category.dao.CategoryDao; import com.elink.esua.epdc.modules.category.entity.CategoryEntity; import com.elink.esua.epdc.modules.category.redis.CategoryRedis; import com.elink.esua.epdc.modules.category.service.CategoryService; +import com.elink.esua.epdc.modules.rocketmq.dto.CategoryModifyDTO; +import com.elink.esua.epdc.modules.rocketmq.producer.CategoryModifyProducer; import com.google.common.collect.Lists; import org.apache.commons.lang3.StringUtils; import org.apache.poi.hssf.usermodel.HSSFCell; @@ -80,7 +83,8 @@ public class CategoryServiceImpl extends BaseServiceImpl groups) { + epdcEventsService.modifyPartyGroupName(groups); + return new Result(); + } + } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/dao/EpdcEventsDao.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/dao/EpdcEventsDao.java index 04f0c83e9..ba36e9b30 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/dao/EpdcEventsDao.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/dao/EpdcEventsDao.java @@ -20,6 +20,7 @@ package com.elink.esua.epdc.modules.events.dao; import com.elink.esua.epdc.commons.mybatis.dao.BaseDao; import com.elink.esua.epdc.commons.tools.utils.Result; import com.elink.esua.epdc.dto.events.*; +import com.elink.esua.epdc.dto.events.form.GroupFormDTO; import com.elink.esua.epdc.dto.events.result.EventAppDetailResultDTO; import com.elink.esua.epdc.dto.issue.form.IssuePendingResponseFormDTO; import com.elink.esua.epdc.dto.issue.result.IssuePendingResponseResultDTO; @@ -144,6 +145,47 @@ public interface EpdcEventsDao extends BaseDao { */ List listIssuePendingResponse(IssuePendingResponseFormDTO formDto); + /** + * + * 查询需要修改组织机构信息事件 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 0:20 + */ + List selectListOfOrganizationInfo(String deptId); + /** + * + * 更新网格名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateGridByDeptId(String newDeptName, Long deptId); + /** + * + * 更新事件表党员群名称 + * + * @params [groups] + * @return void + * @author liuchuang + * @since 2020/3/7 12:54 + */ + void updateBatchPartyGroupName(@Param("groups") List groups); + + /** + * + * 查询需要修改的分类信息 + * + * @params [oldCategoryName] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 16:39 + */ + List selectListOfCategoryInfo(String oldCategoryName); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/service/EpdcEventsService.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/service/EpdcEventsService.java index 8b2294a99..3c244a1a8 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/service/EpdcEventsService.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/service/EpdcEventsService.java @@ -23,12 +23,15 @@ import com.elink.esua.epdc.commons.tools.utils.Result; import com.elink.esua.epdc.dto.events.*; import com.elink.esua.epdc.dto.events.form.EpdcEventSubmitFormDTO; import com.elink.esua.epdc.dto.events.form.EpdcEventsReviewFormDTO; +import com.elink.esua.epdc.dto.events.form.GroupFormDTO; import com.elink.esua.epdc.dto.events.result.EventAppDetailResultDTO; import com.elink.esua.epdc.dto.issue.IssueDTO; import com.elink.esua.epdc.dto.issue.form.IssuePendingResponseFormDTO; import com.elink.esua.epdc.dto.issue.result.IssuePendingResponseResultDTO; import com.elink.esua.epdc.dto.issue.result.IssueStateStatisticsResultDTO; import com.elink.esua.epdc.modules.events.entity.EpdcEventsEntity; +import com.elink.esua.epdc.modules.rocketmq.dto.CategoryModifyDTO; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import java.util.List; import java.util.Map; @@ -216,4 +219,37 @@ public interface EpdcEventsService extends BaseService { * @Date 2020/2/28 12:06 **/ Result checkTopicToIssueFlag(String topicId); + + /** + * + * 事件修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); + + /** + * + * 更新事件表、议题表、项目表党员群名称 + * + * @params [groups] + * @return void + * @author liuchuang + * @since 2020/3/7 12:50 + */ + void modifyPartyGroupName(List groups); + + /** + * + * 修改分类信息 + * + * @params [] + * @return void + * @author liuchuang + * @since 2020/3/7 16:33 + */ + void modifyCategoryInfo(CategoryModifyDTO dto); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/service/impl/EpdcEventsServiceImpl.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/service/impl/EpdcEventsServiceImpl.java index 454a8eaf8..d9dabb534 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/service/impl/EpdcEventsServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/events/service/impl/EpdcEventsServiceImpl.java @@ -40,6 +40,7 @@ import com.elink.esua.epdc.dto.epdc.form.EpdcInformationFormDTO; import com.elink.esua.epdc.dto.events.*; import com.elink.esua.epdc.dto.events.form.EpdcEventSubmitFormDTO; import com.elink.esua.epdc.dto.events.form.EpdcEventsReviewFormDTO; +import com.elink.esua.epdc.dto.events.form.GroupFormDTO; import com.elink.esua.epdc.dto.events.result.EventAppDetailResultDTO; import com.elink.esua.epdc.dto.form.SmsNoticeFormDTO; import com.elink.esua.epdc.dto.issue.IssueDTO; @@ -62,6 +63,8 @@ import com.elink.esua.epdc.modules.issue.entity.IssueHandleEntity; import com.elink.esua.epdc.modules.issue.service.IssueHandleService; import com.elink.esua.epdc.modules.issue.service.IssueService; import com.elink.esua.epdc.modules.item.service.ItemService; +import com.elink.esua.epdc.modules.rocketmq.dto.CategoryModifyDTO; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -572,4 +575,113 @@ public class EpdcEventsServiceImpl extends BaseServiceImpl eventsList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != eventsList && eventsList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, eventsList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + + // 更新网格名称 + baseDao.updateGridByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, eventsList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 1:17 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List eventsList) { + List entities = new ArrayList<>(); + for (EpdcEventsDTO events: eventsList) { + EpdcEventsEntity entity = new EpdcEventsEntity(); + if (StringUtils.isNotEmpty(events.getParentDeptIds()) && StringUtils.isNotEmpty(events.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(events.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(events.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(events.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(events.getAllDeptIds()) && StringUtils.isNotEmpty(events.getAllDeptNames())) { + List allDeptIds = Arrays.asList(events.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(events.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(events.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyPartyGroupName(List groups) { + // 更新事件表党员群名称 + baseDao.updateBatchPartyGroupName(groups); + // 更新议题表党员群名称 + issueService.modifyPartyGroupName(groups); + // 更新项目表党员群名称 + itemService.modifyPartyGroupName(groups); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyCategoryInfo(CategoryModifyDTO dto) { + // 查询需要修改的分类信息 + List eventsList = baseDao.selectListOfCategoryInfo(dto.getOldCategoryName()); + if (null != eventsList && eventsList.size() > 0) { + // 分类信息处理 + List entities = handleCategoryInfo(dto, eventsList); + // 更新分类信息 + updateBatchById(entities); + } + } + + /** + * + * 分类信息处理 + * + * @params [dto, eventsList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 17:00 + */ + private List handleCategoryInfo(CategoryModifyDTO dto, List eventsList) { + List entities = new ArrayList<>(); + for (EpdcEventsDTO events: eventsList) { + if (StringUtils.isNotEmpty(events.getCategoryFullName())) { + List categoryFullName = Arrays.asList(events.getCategoryFullName().split("-")); + int index = categoryFullName.indexOf(dto.getOldCategoryName()); + if (index >= 0) { + categoryFullName.set(index, dto.getNewCategoryName()); + EpdcEventsEntity entity = new EpdcEventsEntity(); + entity.setId(events.getId()); + entity.setCategoryFullName(StringUtils.join(categoryFullName, "-")); + entities.add(entity); + } + } + } + + return entities; + } } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/dao/IssueDao.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/dao/IssueDao.java index 93d41824f..f49030a7b 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/dao/IssueDao.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/dao/IssueDao.java @@ -18,7 +18,9 @@ package com.elink.esua.epdc.modules.issue.dao; import com.elink.esua.epdc.commons.mybatis.dao.BaseDao; +import com.elink.esua.epdc.dto.events.form.GroupFormDTO; import com.elink.esua.epdc.dto.issue.IssueContentDetailDTO; +import com.elink.esua.epdc.dto.issue.IssueDTO; import com.elink.esua.epdc.dto.issue.IssueWaitHandleDetailDTO; import com.elink.esua.epdc.dto.issue.IssueWaitHandleOrClosedDTO; import com.elink.esua.epdc.dto.issue.form.*; @@ -158,4 +160,48 @@ public interface IssueDao extends BaseDao { * @since 2019/11/21 15:16 */ List selectListIssueProgress(String issueId); + + /** + * + * 查询需要修改组织机构信息事件 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 0:20 + */ + List selectListOfOrganizationInfo(String deptId); + + /** + * + * 更新网格名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateGridByDeptId(String newDeptName, Long deptId); + + /** + * + * 更新议题表党员群名称 + * + * @params [groups] + * @return void + * @author liuchuang + * @since 2020/3/7 12:54 + */ + void updateBatchPartyGroupName(@Param("groups") List groups); + + /** + * + * 查询需要修改的分类信息 + * + * @params [oldCategoryName] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 16:39 + */ + List selectListOfCategoryInfo(String oldCategoryName); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/dao/IssueHandleDao.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/dao/IssueHandleDao.java index 0292def24..3c771950b 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/dao/IssueHandleDao.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/dao/IssueHandleDao.java @@ -30,4 +30,14 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface IssueHandleDao extends BaseDao { + /** + * + * 更新操作人部门名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateDeptNameByDeptId(String newDeptName, Long deptId); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/IssueHandleService.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/IssueHandleService.java index 0f1db25c6..80bf7a103 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/IssueHandleService.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/IssueHandleService.java @@ -19,6 +19,7 @@ package com.elink.esua.epdc.modules.issue.service; import com.elink.esua.epdc.commons.mybatis.service.BaseService; import com.elink.esua.epdc.modules.issue.entity.IssueHandleEntity; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; /** * 议题处理表 议题处理表 @@ -37,4 +38,15 @@ public interface IssueHandleService extends BaseService { * @date */ void delete(String[] ids); + + /** + * + * 议题处理进度修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/IssueService.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/IssueService.java index beccfff2e..047e1c757 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/IssueService.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/IssueService.java @@ -21,6 +21,7 @@ import com.elink.esua.epdc.commons.mybatis.service.BaseService; import com.elink.esua.epdc.commons.tools.page.PageData; import com.elink.esua.epdc.commons.tools.utils.Result; import com.elink.esua.epdc.dto.events.EpdcEventsCommentsDTO; +import com.elink.esua.epdc.dto.events.form.GroupFormDTO; import com.elink.esua.epdc.dto.events.result.EventAppDetailResultDTO; import com.elink.esua.epdc.dto.issue.form.*; import com.elink.esua.epdc.dto.issue.IssueContentDetailDTO; @@ -31,6 +32,8 @@ import com.elink.esua.epdc.dto.issue.form.IssueFormDTO; import com.elink.esua.epdc.dto.issue.form.IssueWaitHandleSubmitFormDTO; import com.elink.esua.epdc.dto.issue.result.*; import com.elink.esua.epdc.modules.issue.entity.IssueEntity; +import com.elink.esua.epdc.modules.rocketmq.dto.CategoryModifyDTO; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import org.springframework.web.bind.annotation.RequestBody; import java.util.List; @@ -248,4 +251,37 @@ public interface IssueService extends BaseService { * @since 2019/11/21 15:16 */ List listIssueProgress(String issueId); + + /** + * + * 议题修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); + + /** + * + * 更新议题表党员群名称 + * + * @params [groups] + * @return void + * @author liuchuang + * @since 2020/3/7 12:50 + */ + void modifyPartyGroupName(List groups); + + /** + * + * 修改分类信息 + * + * @params [] + * @return void + * @author liuchuang + * @since 2020/3/7 16:33 + */ + void modifyCategoryInfo(CategoryModifyDTO dto); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/impl/IssueHandleServiceImpl.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/impl/IssueHandleServiceImpl.java index c8491945a..5100805ad 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/impl/IssueHandleServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/issue/service/impl/IssueHandleServiceImpl.java @@ -21,6 +21,7 @@ import com.elink.esua.epdc.commons.mybatis.service.impl.BaseServiceImpl; import com.elink.esua.epdc.modules.issue.dao.IssueHandleDao; import com.elink.esua.epdc.modules.issue.entity.IssueHandleEntity; import com.elink.esua.epdc.modules.issue.service.IssueHandleService; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -42,4 +43,11 @@ public class IssueHandleServiceImpl extends BaseServiceImpl imp sms.setSmsTemplateType(SysSmsTemplateConstant.SMS_TEMPLATE_RESIDENTS_ISSUE_CHANGE_ITEM); issueOverseeResultsTask.sendSmsNotice(sms); } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyOrganizationInfo(OrganizationModifyDTO dto) { + // 查询需要修改组织机构信息议题 + List issueList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != issueList && issueList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, issueList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + + // 更新网格名称 + baseDao.updateGridByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, issueList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 1:17 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List issueList) { + List entities = new ArrayList<>(); + for (IssueDTO issue: issueList) { + IssueEntity entity = new IssueEntity(); + if (StringUtils.isNotEmpty(issue.getParentDeptIds()) && StringUtils.isNotEmpty(issue.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(issue.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(issue.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(issue.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(issue.getAllDeptIds()) && StringUtils.isNotEmpty(issue.getAllDeptNames())) { + List allDeptIds = Arrays.asList(issue.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(issue.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(issue.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyPartyGroupName(List groups) { + // 更新议题表党员群名称 + baseDao.updateBatchPartyGroupName(groups); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyCategoryInfo(CategoryModifyDTO dto) { + // 查询需要修改的分类信息 + List issueList = baseDao.selectListOfCategoryInfo(dto.getOldCategoryName()); + if (null != issueList && issueList.size() > 0) { + // 分类信息处理 + List entities = handleCategoryInfo(dto, issueList); + // 更新分类信息 + updateBatchById(entities); + } + } + + /** + * + * 分类信息处理 + * + * @params [dto, eventsList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 17:00 + */ + private List handleCategoryInfo(CategoryModifyDTO dto, List issueList) { + List entities = new ArrayList<>(); + for (IssueDTO issue: issueList) { + if (StringUtils.isNotEmpty(issue.getCategoryFullName())) { + List categoryFullName = Arrays.asList(issue.getCategoryFullName().split("-")); + int index = categoryFullName.indexOf(dto.getOldCategoryName()); + if (index >= 0) { + categoryFullName.set(index, dto.getNewCategoryName()); + IssueEntity entity = new IssueEntity(); + entity.setId(issue.getId()); + entity.setCategoryFullName(StringUtils.join(categoryFullName, "-")); + entities.add(entity); + } + } + } + + return entities; + } } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemDao.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemDao.java index 89358e90a..6f6f9e49c 100755 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemDao.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemDao.java @@ -18,6 +18,7 @@ package com.elink.esua.epdc.modules.item.dao; import com.elink.esua.epdc.commons.mybatis.dao.BaseDao; +import com.elink.esua.epdc.dto.events.form.GroupFormDTO; import com.elink.esua.epdc.dto.item.ItemDTO; import com.elink.esua.epdc.dto.item.ItemPendingHandleDTO; import com.elink.esua.epdc.dto.item.form.ItemCategoryStatisticsFormDTO; @@ -225,4 +226,48 @@ public interface ItemDao extends BaseDao { * @Date: 2020-01-14 */ List queryParentDeptId(@Param("itemId") String itemId, @Param("deptId") Long deptId); + + /** + * + * 查询需要修改组织机构信息事件 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 0:20 + */ + List selectListOfOrganizationInfo(String deptId); + + /** + * + * 更新网格名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateGridByDeptId(String newDeptName, Long deptId); + + /** + * + * 更新项目表党员群名称 + * + * @params [groups] + * @return void + * @author liuchuang + * @since 2020/3/7 12:54 + */ + void updateBatchPartyGroupName(@Param("groups") List groups); + + /** + * + * 查询需要修改的分类信息 + * + * @params [oldCategoryName] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 16:39 + */ + List selectListOfCategoryInfo(String oldCategoryName); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemDeptDao.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemDeptDao.java index f06d93adf..27b97ec8d 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemDeptDao.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemDeptDao.java @@ -70,4 +70,15 @@ public interface ItemDeptDao extends BaseDao { * @Date: 2019/9/17 9:08 */ List selectListOfEvaluateDepts(String itemId, Long deptId); + + /** + * + * 更新部门名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateDeptNameByDeptId(String newDeptName, Long deptId); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemEvaluateDeptDao.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemEvaluateDeptDao.java index 53f0cb32b..38be0873a 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemEvaluateDeptDao.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemEvaluateDeptDao.java @@ -44,4 +44,15 @@ public interface ItemEvaluateDeptDao extends BaseDao { */ List selectListOfDeptEvaluateByItemId(String itemId); + /** + * + * 更新被评价部门名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateDeptNameByDeptId(String newDeptName, Long deptId); + } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemHandleProcessDao.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemHandleProcessDao.java index cf5e948dc..805da2e6e 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemHandleProcessDao.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemHandleProcessDao.java @@ -42,4 +42,15 @@ public interface ItemHandleProcessDao extends BaseDao { */ void insertItemHandleProcess(ItemHandleProcessDTO dto); + /** + * + * 更新操作人部门名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateDeptNameByDeptId(String newDeptName, Long deptId); + } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemInformationDao.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemInformationDao.java index dac96f84f..cea656268 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemInformationDao.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/dao/ItemInformationDao.java @@ -55,4 +55,15 @@ public interface ItemInformationDao extends BaseDao { */ int updateInformationReadFlag(ItemInformationFormDTO formDto); + /** + * + * 更新处理部门名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateDeptNameByDeptId(String newDeptName, Long deptId); + } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemDeptService.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemDeptService.java index c3cee906b..f6677528c 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemDeptService.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemDeptService.java @@ -22,6 +22,7 @@ import com.elink.esua.epdc.dto.item.ItemDeptDTO; import com.elink.esua.epdc.dto.item.ItemEvaluateDeptDTO; import com.elink.esua.epdc.dto.item.form.ItemHandleSubmitFormDTO; import com.elink.esua.epdc.modules.item.entity.ItemDeptEntity; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import java.util.List; @@ -89,4 +90,15 @@ public interface ItemDeptService extends BaseService { * @Date: 2019/9/17 9:09 */ List listOfEvaluateDepts(String itemId, Long deptId); + + /** + * + * 项目部门关系表修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemEvaluateDeptService.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemEvaluateDeptService.java index 009e28528..1008d3b6b 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemEvaluateDeptService.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemEvaluateDeptService.java @@ -20,6 +20,7 @@ import com.elink.esua.epdc.commons.mybatis.service.BaseService; import com.elink.esua.epdc.dto.item.ItemEvaluateDeptDTO; import com.elink.esua.epdc.dto.item.result.ItemDeptEvaluateResultDTO; import com.elink.esua.epdc.modules.item.entity.ItemEvaluateDeptEntity; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import java.util.List; import java.util.Map; @@ -61,4 +62,15 @@ public interface ItemEvaluateDeptService extends BaseService listOfDeptEvaluateByItemId(String itemId); + + /** + * + * 修改被评价部门名称 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemHandleProcessService.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemHandleProcessService.java index 7d3493e49..a32bd2334 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemHandleProcessService.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemHandleProcessService.java @@ -20,6 +20,7 @@ package com.elink.esua.epdc.modules.item.service; import com.elink.esua.epdc.commons.mybatis.service.BaseService; import com.elink.esua.epdc.dto.item.ItemHandleProcessDTO; import com.elink.esua.epdc.modules.item.entity.ItemHandleProcessEntity; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; /** @@ -50,4 +51,15 @@ public interface ItemHandleProcessService extends BaseService> notice(ItemInformationFormDTO formDto); + + /** + * + * 修改处理部门名称 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemService.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemService.java index 7827cfa9f..2541e571a 100755 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemService.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/ItemService.java @@ -21,11 +21,14 @@ import com.elink.esua.epdc.commons.mybatis.service.BaseService; import com.elink.esua.epdc.commons.tools.page.PageData; import com.elink.esua.epdc.commons.tools.utils.Result; import com.elink.esua.epdc.dto.events.EpdcEventsCommentsDTO; +import com.elink.esua.epdc.dto.events.form.GroupFormDTO; import com.elink.esua.epdc.dto.item.ItemDTO; import com.elink.esua.epdc.dto.item.ItemPendingHandleDTO; import com.elink.esua.epdc.dto.item.form.*; import com.elink.esua.epdc.dto.item.result.*; import com.elink.esua.epdc.modules.item.entity.ItemEntity; +import com.elink.esua.epdc.modules.rocketmq.dto.CategoryModifyDTO; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import java.util.List; import java.util.Map; @@ -321,4 +324,37 @@ public interface ItemService extends BaseService { * @Date 2020/1/13 16:55 **/ Result> queryHandleCategories(); + + /** + * + * 项目修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); + + /** + * + * 更新项目表党员群名称 + * + * @params [groups] + * @return void + * @author liuchuang + * @since 2020/3/7 12:50 + */ + void modifyPartyGroupName(List groups); + + /** + * + * 修改分类信息 + * + * @params [] + * @return void + * @author liuchuang + * @since 2020/3/7 16:33 + */ + void modifyCategoryInfo(CategoryModifyDTO dto); } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/impl/ItemDeptServiceImpl.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/impl/ItemDeptServiceImpl.java index 930e0a17e..11dda72f9 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/impl/ItemDeptServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/impl/ItemDeptServiceImpl.java @@ -25,6 +25,7 @@ import com.elink.esua.epdc.dto.item.result.ItemCirculationDeptResultDTO; import com.elink.esua.epdc.modules.item.dao.ItemDeptDao; import com.elink.esua.epdc.modules.item.entity.ItemDeptEntity; import com.elink.esua.epdc.modules.item.service.ItemDeptService; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -86,4 +87,11 @@ public class ItemDeptServiceImpl extends BaseServiceImpl>().ok(data); } + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyOrganizationInfo(OrganizationModifyDTO dto) { + // 更新部门名称 + baseDao.updateDeptNameByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/impl/ItemServiceImpl.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/impl/ItemServiceImpl.java index 6d9f2b03d..2a3c78bd6 100755 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/impl/ItemServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/item/service/impl/ItemServiceImpl.java @@ -39,6 +39,7 @@ import com.elink.esua.epdc.dto.MenuNoticeDTO; import com.elink.esua.epdc.dto.SysDeptDTO; import com.elink.esua.epdc.dto.epdc.form.EpdcInformationFormDTO; import com.elink.esua.epdc.dto.events.EpdcEventsCommentsDTO; +import com.elink.esua.epdc.dto.events.form.GroupFormDTO; import com.elink.esua.epdc.dto.form.SmsNoticeFormDTO; import com.elink.esua.epdc.dto.issue.result.IssueProgressResultDTO; import com.elink.esua.epdc.dto.item.*; @@ -71,6 +72,8 @@ import com.elink.esua.epdc.modules.item.dao.ItemDao; import com.elink.esua.epdc.modules.item.dao.ItemGridPlatformDao; import com.elink.esua.epdc.modules.item.entity.*; import com.elink.esua.epdc.modules.item.service.*; +import com.elink.esua.epdc.modules.rocketmq.dto.CategoryModifyDTO; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -1354,4 +1357,109 @@ public class ItemServiceImpl extends BaseServiceImpl implem return itemHandleResultDTOS; } + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyOrganizationInfo(OrganizationModifyDTO dto) { + // 查询需要修改组织机构信息项目 + List itemList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != itemList && itemList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, itemList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + + // 更新网格名称 + baseDao.updateGridByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, eventsList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 1:17 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List itemList) { + List entities = new ArrayList<>(); + for (ItemDTO item: itemList) { + ItemEntity entity = new ItemEntity(); + if (StringUtils.isNotEmpty(item.getParentDeptIds()) && StringUtils.isNotEmpty(item.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(item.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(item.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(item.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(item.getAllDeptIds()) && StringUtils.isNotEmpty(item.getAllDeptNames())) { + List allDeptIds = Arrays.asList(item.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(item.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(item.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyPartyGroupName(List groups) { + // 更新项目表党员群名称 + baseDao.updateBatchPartyGroupName(groups); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyCategoryInfo(CategoryModifyDTO dto) { + // 查询需要修改的分类信息 + List itemList = baseDao.selectListOfCategoryInfo(dto.getOldCategoryName()); + if (null != itemList && itemList.size() > 0) { + // 分类信息处理 + List entities = handleCategoryInfo(dto, itemList); + // 更新分类信息 + updateBatchById(entities); + } + } + + /** + * + * 分类信息处理 + * + * @params [dto, eventsList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 17:00 + */ + private List handleCategoryInfo(CategoryModifyDTO dto, List itemList) { + List entities = new ArrayList<>(); + for (ItemDTO item: itemList) { + if (StringUtils.isNotEmpty(item.getCategoryFullName())) { + List categoryFullName = Arrays.asList(item.getCategoryFullName().split("-")); + int index = categoryFullName.indexOf(dto.getOldCategoryName()); + if (index >= 0) { + categoryFullName.set(index, dto.getNewCategoryName()); + ItemEntity entity = new ItemEntity(); + entity.setId(item.getId()); + entity.setCategoryFullName(StringUtils.join(categoryFullName, "-")); + entities.add(entity); + } + } + } + + return entities; + } + } diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/consumer/CategoryModifyConsumer.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/consumer/CategoryModifyConsumer.java new file mode 100644 index 000000000..2b4f38c86 --- /dev/null +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/consumer/CategoryModifyConsumer.java @@ -0,0 +1,57 @@ +package com.elink.esua.epdc.modules.rocketmq.consumer; + +import com.alibaba.fastjson.JSONObject; +import com.elink.esua.epdc.commons.tools.constant.RocketMqConstant; +import com.elink.esua.epdc.modules.events.service.EpdcEventsService; +import com.elink.esua.epdc.modules.issue.service.IssueService; +import com.elink.esua.epdc.modules.item.service.ItemService; +import com.elink.esua.epdc.modules.rocketmq.dto.CategoryModifyDTO; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.MessageModel; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * 分类信息修改-监听MQ消息 + * + * @Author:liuchuang + * @Date:2020/3/7 16:29 + */ +@Slf4j +@Component +@RocketMQMessageListener(topic = RocketMqConstant.MQ_TOPIC_CATEGORY, consumerGroup = "${rocketmq.consumer.category-group}", messageModel = MessageModel.BROADCASTING) +public class CategoryModifyConsumer implements RocketMQListener { + + @Autowired + private EpdcEventsService epdcEventsService; + + @Autowired + private IssueService issueService; + + @Autowired + private ItemService itemService; + + @Override + public void onMessage(MessageExt messageExt) { + log.info("EPDC-EVENTS-SERVER消费消息START:{topic:{}, msgId:{}}", RocketMqConstant.MQ_TOPIC_CATEGORY, messageExt.getMsgId()); + try { + String charset = "UTF-8"; + String body = new String(messageExt.getBody(), charset); + CategoryModifyDTO dto = JSONObject.parseObject(body, CategoryModifyDTO.class); + // 事件表修改分类信息 + epdcEventsService.modifyCategoryInfo(dto); + // 议题表修改分类信息 + issueService.modifyCategoryInfo(dto); + // 项目表修改分类信息 + itemService.modifyCategoryInfo(dto); + log.info("EPDC-EVENTS-SERVER消费消息END:{topic:{}, msgId:{}, body:{}}", RocketMqConstant.MQ_TOPIC_CATEGORY, messageExt.getMsgId(), body); + } catch (Exception e) { + log.info("EPDC-EVENTS-SERVER消费消息失败:msgId:{}", messageExt.getMsgId()); + e.printStackTrace(); + } + } +} diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/consumer/OrganizationModifyConsumer.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/consumer/OrganizationModifyConsumer.java new file mode 100644 index 000000000..3d6f3db56 --- /dev/null +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/consumer/OrganizationModifyConsumer.java @@ -0,0 +1,83 @@ +package com.elink.esua.epdc.modules.rocketmq.consumer; + +import com.alibaba.fastjson.JSONObject; +import com.elink.esua.epdc.commons.tools.constant.RocketMqConstant; +import com.elink.esua.epdc.modules.events.service.EpdcEventsService; +import com.elink.esua.epdc.modules.issue.service.IssueHandleService; +import com.elink.esua.epdc.modules.issue.service.IssueService; +import com.elink.esua.epdc.modules.item.service.*; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.MessageModel; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * 组织机构信息修改-监听MQ消息 + * + * @Author:liuchuang + * @Date:2020/3/6 0:21 + */ +@Slf4j +@Component +@RocketMQMessageListener(topic = RocketMqConstant.MQ_TOPIC_ORGANIZATION, consumerGroup = "${rocketmq.consumer.group}", messageModel = MessageModel.BROADCASTING) +public class OrganizationModifyConsumer implements RocketMQListener { + + @Autowired + private EpdcEventsService epdcEventsService; + + @Autowired + private IssueService issueService; + + @Autowired + private IssueHandleService issueHandleService; + + @Autowired + private ItemService itemService; + + @Autowired + private ItemDeptService itemDeptService; + + @Autowired + private ItemEvaluateDeptService itemEvaluateDeptService; + + @Autowired + private ItemHandleProcessService itemHandleProcessService; + + @Autowired + private ItemInformationService itemInformationService; + + @Override + public void onMessage(MessageExt messageExt) { + log.info("EPDC-EVENTS-SERVER消费消息START:{topic:{}, msgId:{}}", RocketMqConstant.MQ_TOPIC_ORGANIZATION, messageExt.getMsgId()); + try { + String charset = "UTF-8"; + String body = new String(messageExt.getBody(), charset); + OrganizationModifyDTO dto = JSONObject.parseObject(body, OrganizationModifyDTO.class); + // 事件修改组织机构信息 + epdcEventsService.modifyOrganizationInfo(dto); + // 议题修改组织机构信息 + issueService.modifyOrganizationInfo(dto); + // 议题处理进度修改操作人部门名称 + issueHandleService.modifyOrganizationInfo(dto); + // 项目修改组织机构信息 + itemService.modifyOrganizationInfo(dto); + // 项目部门关系表修改部门名称 + itemDeptService.modifyOrganizationInfo(dto); + // 项目部门评价表修改被评价部门名称 + itemEvaluateDeptService.modifyOrganizationInfo(dto); + // 项目处理进度表修改操作人部门 + itemHandleProcessService.modifyOrganizationInfo(dto); + //项目消息表修改处理部门 + itemInformationService.modifyOrganizationInfo(dto); + log.info("EPDC-EVENTS-SERVER消费消息END:{topic:{}, msgId:{}, body:{}}", RocketMqConstant.MQ_TOPIC_ORGANIZATION, messageExt.getMsgId(), body); + } catch (Exception e) { + log.info("EPDC-EVENTS-SERVER消费消息失败:msgId:{}", messageExt.getMsgId()); + e.printStackTrace(); + } + } +} diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/dto/CategoryModifyDTO.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/dto/CategoryModifyDTO.java new file mode 100644 index 000000000..1959c9e37 --- /dev/null +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/dto/CategoryModifyDTO.java @@ -0,0 +1,32 @@ +package com.elink.esua.epdc.modules.rocketmq.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * + * RocketMQ消息DTO + * + * @Author:liuchuang + * @Date:2020/3/7 16:21 + */ +@Data +public class CategoryModifyDTO implements Serializable { + private static final long serialVersionUID = -5012212832912602966L; + + /** + * 分类ID + */ + private Long categoryId; + + /** + * 旧分类名称 + */ + private String oldCategoryName; + + /** + * 新分类名称 + */ + private String newCategoryName; +} diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/dto/OrganizationModifyDTO.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/dto/OrganizationModifyDTO.java new file mode 100644 index 000000000..f0f6ff6ef --- /dev/null +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/dto/OrganizationModifyDTO.java @@ -0,0 +1,37 @@ +package com.elink.esua.epdc.modules.rocketmq.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * + * 组织机构信息修改-接收MQ消息DTO + * + * @Author:liuchuang + * @Date:2020/3/6 22:34 + */ +@Data +public class OrganizationModifyDTO implements Serializable { + private static final long serialVersionUID = 6288521726874495827L; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 旧部门名称 + */ + private String oldDeptName; + + /** + * 新部门名称 + */ + private String newDeptName; + + /** + * 部门类型 + */ + private String typeKey; +} diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/producer/CategoryModifyProducer.java b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/producer/CategoryModifyProducer.java new file mode 100644 index 000000000..f2f92311d --- /dev/null +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/java/com/elink/esua/epdc/modules/rocketmq/producer/CategoryModifyProducer.java @@ -0,0 +1,43 @@ +package com.elink.esua.epdc.modules.rocketmq.producer; + +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.client.producer.SendResult; +import org.apache.rocketmq.common.message.Message; +import org.apache.rocketmq.spring.core.RocketMQTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * 分类信息修改-发送MQ消息 + * + * @Author:liuchuang + * @Date:2020/3/7 16:14 + */ +@Slf4j +@Component +public class CategoryModifyProducer { + + @Autowired + private RocketMQTemplate rocketMQTemplate; + + /** + * + * 发送消息 + * + * @params [topic, tag, keys, body] + * @return void + * @author liuchuang + * @since 2020/3/6 21:09 + */ + public void sendMessage(String topic, String tag, String keys, String body) { + Message message = new Message(topic, tag, keys, body.getBytes()); + try { + SendResult sendResult = rocketMQTemplate.getProducer().send(message); + log.info("EPDC-EVENTS-SERVER发送消息结果:{sendStatus:{}, topic:{}, msgId:{}}", sendResult.getSendStatus(), topic, sendResult.getMsgId()); + } catch (Exception e) { + log.error("EPDC-EVENTS-SERVER发送消息异常:{topic:{}, tag:{}, keys:{}, body:{}}", topic, tag, keys, body); + e.printStackTrace(); + } + } +} diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/application.yml b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/application.yml index 28f416c29..200fa69cd 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/application.yml +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/application.yml @@ -112,3 +112,11 @@ wx: work: @work.wx.ma.appId@ # 数据分析端的appId analysis: @analysis.wx.ma.appId@ + +rocketmq: + name-server: @rocketmq.name.server@ + producer: + group: @rocketmq.producer.category.group@ + consumer: + group: @rocketmq.consumer.group@ + category-group: @rocketmq.consumer.category.group@ diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/events/EpdcEventsDao.xml b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/events/EpdcEventsDao.xml index 7ce91bf7f..14d41bcaa 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/events/EpdcEventsDao.xml +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/events/EpdcEventsDao.xml @@ -331,5 +331,37 @@ LIMIT #{pageIndex},#{pageSize} + + + + UPDATE epdc_events SET GRID = #{newDeptName}, UPDATED_TIME = NOW() WHERE GRID_ID = #{deptId} + + + + + UPDATE epdc_events SET GROUP_NAME = #{group.groupName}, UPDATED_TIME = NOW() WHERE GROUP_ID = #{group.id} + + + + diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/issue/IssueDao.xml b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/issue/IssueDao.xml index f5f63a732..a893ec266 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/issue/IssueDao.xml +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/issue/IssueDao.xml @@ -596,4 +596,37 @@ img.CREATED_TIME + + + + UPDATE epdc_issue SET GRID = #{newDeptName}, UPDATED_TIME = NOW() WHERE GRID_ID = #{deptId} + + + + + UPDATE epdc_issue SET GROUP_NAME = #{group.groupName}, UPDATED_TIME = NOW() WHERE GROUP_ID = #{group.id} + + + + + diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/issue/IssueHandleDao.xml b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/issue/IssueHandleDao.xml index d8150fb2b..2f166f2b6 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/issue/IssueHandleDao.xml +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/issue/IssueHandleDao.xml @@ -3,4 +3,7 @@ + + UPDATE epdc_issue_handle SET HANDLER_DEPT = #{newDeptName}, UPDATED_TIME = NOW() WHERE HANDLER_DEPT_ID = #{deptId} + diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemDao.xml b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemDao.xml index b8696e0c5..78154a31f 100755 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemDao.xml +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemDao.xml @@ -904,4 +904,37 @@ AND d.ITEM_ID = #{itemId} + + + + + UPDATE epdc_item SET GRID = #{newDeptName}, UPDATED_TIME = NOW() WHERE GRID_ID = #{deptId} + + + + + UPDATE epdc_item SET GROUP_NAME = #{group.groupName}, UPDATED_TIME = NOW() WHERE GROUP_ID = #{group.id} + + + + diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemDeptDao.xml b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemDeptDao.xml index 97938a5b7..65d1e399f 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemDeptDao.xml +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemDeptDao.xml @@ -26,4 +26,8 @@ AND ITEM_ID = #{itemId} AND DEPT_ID ]]> #{deptId} + + + UPDATE epdc_item_dept SET DEPT_NAME = #{newDeptName}, UPDATED_TIME = NOW() WHERE DEPT_ID = #{deptId} + diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemEvaluateDeptDao.xml b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemEvaluateDeptDao.xml index 70b7340b6..93ac18281 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemEvaluateDeptDao.xml +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemEvaluateDeptDao.xml @@ -24,4 +24,8 @@ CREATED_TIME DESC + + UPDATE epdc_item_evaluate_dept SET DEPT_NAME = #{newDeptName}, UPDATED_TIME = NOW() WHERE DEPT_ID = #{deptId} + + \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemHandleProcessDao.xml b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemHandleProcessDao.xml index bda6c5fc4..ecb04e306 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemHandleProcessDao.xml +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemHandleProcessDao.xml @@ -6,4 +6,8 @@ INSERT INTO epdc_item_handle_process ( ID, ITEM_ID, STATE, HANDLE_ADVICE, OUT_HANDLE_ADVICE, HANDLER_DEPT, REVISION, CREATED_BY, CREATED_TIME, UPDATED_BY, UPDATED_TIME, DEL_FLAG ) VALUES (#{id}, #{itemId}, #{state}, #{handleAdvice}, #{outHandleAdvice}, #{handlerDept}, 0, '网格化平台', #{createdTime}, '网格化平台', #{updatedTime}, '0') + + + UPDATE epdc_item_handle_process SET HANDLER_DEPT = #{newDeptName}, UPDATED_TIME = NOW() WHERE HANDLER_DEPT_ID = #{deptId} + diff --git a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemInformationDao.xml b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemInformationDao.xml index 9a2d4fea3..8c3ef7c0a 100644 --- a/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemInformationDao.xml +++ b/esua-epdc/epdc-module/epdc-events/epdc-events-server/src/main/resources/mapper/item/ItemInformationDao.xml @@ -53,4 +53,8 @@ #{deptIdItem} + + + UPDATE epdc_item_information SET HANDLE_DEPT = #{newDeptName}, UPDATED_TIME = NOW() WHERE HANDLE_DEPT_ID = #{deptId} + diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/pom.xml b/esua-epdc/epdc-module/epdc-group/epdc-group-server/pom.xml index 9249da585..a8cb86426 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/pom.xml +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/pom.xml @@ -51,6 +51,12 @@ feign-httpclient 10.3.0 + + + org.apache.rocketmq + rocketmq-spring-boot-starter + 2.0.3 + @@ -131,6 +137,9 @@ false 47.104.224.45:8848 + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup @@ -155,6 +164,9 @@ true 47.104.224.45:8848 219.146.91.110 + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/feign/EventFeignClient.java b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/feign/EventFeignClient.java index 78db731fb..585a0082b 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/feign/EventFeignClient.java +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/feign/EventFeignClient.java @@ -4,6 +4,8 @@ import com.elink.esua.epdc.commons.tools.constant.ServiceConstant; import com.elink.esua.epdc.commons.tools.utils.Result; import com.elink.esua.epdc.dto.comment.EpdcCommentsAndAttitudeFromTopicFormDTO; import com.elink.esua.epdc.dto.events.form.EpdcEventSubmitFormDTO; +import com.elink.esua.epdc.dto.events.form.GroupFormDTO; +import com.elink.esua.epdc.dto.group.GroupDTO; import com.elink.esua.epdc.dto.issue.IssueDTO; import com.elink.esua.epdc.modules.feign.fallback.EventFeignClientFallback; import org.springframework.cloud.openfeign.FeignClient; @@ -12,6 +14,8 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import java.util.List; + /** * * 事件模块调用 @@ -55,4 +59,16 @@ public interface EventFeignClient { **/ @GetMapping("events/epdcevents/checkTopicToIssueFlag/{topicId}") Result checkTopicToIssueFlag(@PathVariable("topicId") String topicId); + + /** + * + * 更新事件表、议题表、项目表党员群名称 + * + * @params [groups] + * @return com.elink.esua.epdc.commons.tools.utils.Result + * @author liuchuang + * @since 2020/3/7 12:39 + */ + @PostMapping(value = "events/epdc-app/event/modifyGroupName", consumes = MediaType.APPLICATION_JSON_VALUE) + Result modifyPartyGroupName(List groups); } diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/feign/fallback/EventFeignClientFallback.java b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/feign/fallback/EventFeignClientFallback.java index 1b431be85..984c409a4 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/feign/fallback/EventFeignClientFallback.java +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/feign/fallback/EventFeignClientFallback.java @@ -5,10 +5,14 @@ import com.elink.esua.epdc.commons.tools.utils.ModuleUtils; import com.elink.esua.epdc.commons.tools.utils.Result; import com.elink.esua.epdc.dto.comment.EpdcCommentsAndAttitudeFromTopicFormDTO; import com.elink.esua.epdc.dto.events.form.EpdcEventSubmitFormDTO; +import com.elink.esua.epdc.dto.events.form.GroupFormDTO; +import com.elink.esua.epdc.dto.group.GroupDTO; import com.elink.esua.epdc.dto.issue.IssueDTO; import com.elink.esua.epdc.modules.feign.EventFeignClient; import org.springframework.stereotype.Component; +import java.util.List; + /** * @Author:liuchuang * @Date:2019/11/8 13:36 @@ -30,4 +34,9 @@ public class EventFeignClientFallback implements EventFeignClient { public Result checkTopicToIssueFlag(String topicId) { return ModuleUtils.feignConError(ServiceConstant.EPDC_EVENTS_SERVER, "checkTopicToIssueFlag", topicId); } + + @Override + public Result modifyPartyGroupName(List groups) { + return ModuleUtils.feignConError(ServiceConstant.EPDC_EVENTS_SERVER, "checkTopicToIssueFlag", groups); + } } diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/dao/GroupDao.java b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/dao/GroupDao.java index d4956c299..7b1db6363 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/dao/GroupDao.java +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/dao/GroupDao.java @@ -166,4 +166,37 @@ public interface GroupDao extends BaseDao { * @Date: 2020-01-08 */ String queryGroupUserMOBILE(String groupId); + + /** + * + * 查询需要修改组织机构信息邻里党群 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 2:08 + */ + List selectListOfOrganizationInfo(String deptId); + + /** + * + * 更新网格名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateGridByDeptId(String newDeptName, Long deptId); + + /** + * + * 查询需要修改名称的党员群 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 2:08 + */ + List selectListOfPartyGroups(String deptId); } diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/service/GroupService.java b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/service/GroupService.java index 9d4c15f9a..e15319a6b 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/service/GroupService.java +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/service/GroupService.java @@ -25,6 +25,7 @@ import com.elink.esua.epdc.dto.group.*; import com.elink.esua.epdc.dto.group.form.*; import com.elink.esua.epdc.dto.group.result.*; import com.elink.esua.epdc.modules.group.entity.GroupEntity; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import java.util.List; import java.util.Map; @@ -292,4 +293,15 @@ public interface GroupService extends BaseService { * @Date 2019/12/19 13:04 **/ Result> listPartyMemberGridId(); + + /** + * + * 邻里党群修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/service/impl/GroupServiceImpl.java b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/service/impl/GroupServiceImpl.java index 1067eb562..283e5f63c 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/service/impl/GroupServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/group/service/impl/GroupServiceImpl.java @@ -23,6 +23,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.elink.esua.epdc.commons.mybatis.service.impl.BaseServiceImpl; import com.elink.esua.epdc.commons.tools.constant.FieldConstant; import com.elink.esua.epdc.commons.tools.constant.NumConstant; +import com.elink.esua.epdc.commons.tools.constant.OrganizationTypeConstant; import com.elink.esua.epdc.commons.tools.page.PageData; import com.elink.esua.epdc.commons.tools.utils.ConvertUtils; import com.elink.esua.epdc.commons.tools.utils.Result; @@ -33,6 +34,7 @@ import com.elink.esua.epdc.dto.constant.GroupConstant; import com.elink.esua.epdc.dto.constant.GroupNoticeConstant; import com.elink.esua.epdc.dto.epdc.form.EpdcInformationFormDTO; import com.elink.esua.epdc.dto.epdc.result.EpdcGridUserResultDTO; +import com.elink.esua.epdc.dto.events.form.GroupFormDTO; import com.elink.esua.epdc.dto.form.SmsNoticeFormDTO; import com.elink.esua.epdc.dto.group.*; import com.elink.esua.epdc.dto.enums.GroupStateEnum; @@ -42,13 +44,16 @@ import com.elink.esua.epdc.dto.group.result.*; import com.elink.esua.epdc.enums.ItemHandleCategoryEnum; import com.elink.esua.epdc.modules.async.IssueOverseeResultsTask; import com.elink.esua.epdc.modules.async.NewsTask; +import com.elink.esua.epdc.modules.feign.EventFeignClient; import com.elink.esua.epdc.modules.feign.UserFeignClient; import com.elink.esua.epdc.modules.group.dao.GroupDao; import com.elink.esua.epdc.modules.group.entity.GroupEntity; import com.elink.esua.epdc.modules.group.entity.UserGroupEntity; import com.elink.esua.epdc.modules.group.service.GroupService; import com.elink.esua.epdc.modules.group.service.UserGroupService; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import com.elink.esua.epdc.modules.topic.service.GroupTopicUserReadService; +import com.elink.esua.epdc.modules.topic.service.TopicService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -84,6 +89,12 @@ public class GroupServiceImpl extends BaseServiceImpl imp @Autowired private IssueOverseeResultsTask issueOverseeResultsTask; + @Autowired + private TopicService topicService; + + @Autowired + private EventFeignClient eventFeignClient; + @Override public PageData page(Map params) { IPage page = getPage(params); @@ -541,4 +552,100 @@ public class GroupServiceImpl extends BaseServiceImpl imp } issueOverseeResultsTask.sendSmsNotice(sms); } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyOrganizationInfo(OrganizationModifyDTO dto) { + // 查询需要修改组织机构信息邻里党群 + List groupList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != groupList && groupList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, groupList); + // 更新邻里党群组织机构信息 + updateBatchById(entities); + } + // 更新网格名称 + baseDao.updateGridByDeptId(dto.getNewDeptName(), dto.getDeptId()); + // 修改网格党员群名称 + if (OrganizationTypeConstant.ORG_TYPE_COMMUNITY_PARTY.equals(dto.getTypeKey()) + || OrganizationTypeConstant.ORG_TYPE_GRID_PARTY.equals(dto.getTypeKey())) { + // 查询需要修改名称的党员群 + List partyGroups = baseDao.selectListOfPartyGroups(dto.getDeptId().toString()); + if (null != partyGroups && partyGroups.size() > 0) { + List partyEntities = createPartyGroupName(partyGroups); + // 更新党员群名称 + updateBatchById(partyEntities); + // 更新话题表党员群名称 + topicService.modifyPartyGroupNameByGroupId(ConvertUtils.sourceToTarget(partyEntities, GroupDTO.class)); + // 更新事件表、议题表、项目表党员群名称 + eventFeignClient.modifyPartyGroupName(ConvertUtils.sourceToTarget(partyEntities, GroupFormDTO.class)); + } + } + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, topicList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 2:14 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List groupList) { + List entities = new ArrayList<>(); + for (GroupDTO group: groupList) { + GroupEntity entity = new GroupEntity(); + if (StringUtils.isNotEmpty(group.getParentDeptIds()) && StringUtils.isNotEmpty(group.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(group.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(group.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(group.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(group.getAllDeptIds()) && StringUtils.isNotEmpty(group.getAllDeptNames())) { + List allDeptIds = Arrays.asList(group.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(group.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(group.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } + + /** + * + * 生成新的党员群名称 + * + * @params [partyGroups] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 12:08 + */ + private List createPartyGroupName(List partyGroups) { + List groupEntities = new ArrayList<>(); + for (GroupDTO group: partyGroups) { + String[] allDeptNames = group.getAllDeptNames().split("-"); + int len = allDeptNames.length; + if (len == 4) { + GroupEntity entity = new GroupEntity(); + entity.setId(group.getId()); + entity.setGroupName(allDeptNames[len-2]+allDeptNames[len-1]+"党员群"); + groupEntities.add(entity); + } + } + + return groupEntities; + } } diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/rocketmq/consumer/OrganizationModifyConsumer.java b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/rocketmq/consumer/OrganizationModifyConsumer.java new file mode 100644 index 000000000..8e3a77453 --- /dev/null +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/rocketmq/consumer/OrganizationModifyConsumer.java @@ -0,0 +1,51 @@ +package com.elink.esua.epdc.modules.rocketmq.consumer; + +import com.alibaba.fastjson.JSONObject; +import com.elink.esua.epdc.commons.tools.constant.RocketMqConstant; +import com.elink.esua.epdc.modules.group.service.GroupService; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; +import com.elink.esua.epdc.modules.topic.service.TopicService; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.MessageModel; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * 组织机构信息修改-监听MQ消息 + * + * @Author:liuchuang + * @Date:2020/3/7 1:54 + */ +@Slf4j +@Component +@RocketMQMessageListener(topic = RocketMqConstant.MQ_TOPIC_ORGANIZATION, consumerGroup = "${rocketmq.consumer.group}", messageModel = MessageModel.BROADCASTING) +public class OrganizationModifyConsumer implements RocketMQListener { + + @Autowired + private GroupService groupService; + + @Autowired + private TopicService topicService; + + @Override + public void onMessage(MessageExt messageExt) { + log.info("EPDC-GROUP-SERVER消费消息START:{topic:{}, msgId:{}}", RocketMqConstant.MQ_TOPIC_ORGANIZATION, messageExt.getMsgId()); + try { + String charset = "UTF-8"; + String body = new String(messageExt.getBody(), charset); + OrganizationModifyDTO dto = JSONObject.parseObject(body, OrganizationModifyDTO.class); + // 话题修改组织机构信息 + topicService.modifyOrganizationInfo(dto); + // 邻里党群修改组织机构信息 + groupService.modifyOrganizationInfo(dto); + log.info("EPDC-GROUP-SERVER消费消息END:{topic:{}, msgId:{}, body:{}}", RocketMqConstant.MQ_TOPIC_ORGANIZATION, messageExt.getMsgId(), body); + } catch (Exception e) { + log.info("EPDC-GROUP-SERVER消费消息失败:msgId:{}", messageExt.getMsgId()); + e.printStackTrace(); + } + } +} diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/rocketmq/dto/OrganizationModifyDTO.java b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/rocketmq/dto/OrganizationModifyDTO.java new file mode 100644 index 000000000..379595fcd --- /dev/null +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/rocketmq/dto/OrganizationModifyDTO.java @@ -0,0 +1,37 @@ +package com.elink.esua.epdc.modules.rocketmq.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * + * 组织机构信息修改-接收MQ消息DTO + * + * @Author:liuchuang + * @Date:2020/3/7 1:53 + */ +@Data +public class OrganizationModifyDTO implements Serializable { + private static final long serialVersionUID = 6288521726874495827L; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 旧部门名称 + */ + private String oldDeptName; + + /** + * 新部门名称 + */ + private String newDeptName; + + /** + * 部门类型 + */ + private String typeKey; +} diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/dao/TopicDao.java b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/dao/TopicDao.java index ab96687f0..075d0016a 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/dao/TopicDao.java +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/dao/TopicDao.java @@ -19,6 +19,7 @@ package com.elink.esua.epdc.modules.topic.dao; import com.elink.esua.epdc.commons.mybatis.dao.BaseDao; import com.elink.esua.epdc.dto.events.form.EpdcEventSubmitFormDTO; +import com.elink.esua.epdc.dto.group.GroupDTO; import com.elink.esua.epdc.dto.topic.TopicDTO; import com.elink.esua.epdc.dto.topic.TopicDetailDTO; import com.elink.esua.epdc.dto.topic.form.TopicListFormDTO; @@ -26,6 +27,7 @@ import com.elink.esua.epdc.dto.topic.result.TopicDetailResultDTO; import com.elink.esua.epdc.dto.topic.result.TopicListResultDTO; import com.elink.esua.epdc.modules.topic.entity.TopicEntity; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; @@ -99,4 +101,37 @@ public interface TopicDao extends BaseDao { */ TopicDetailDTO selectOneOfTopic(String id); + /** + * + * 查询需要修改组织机构信息事件 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 2:08 + */ + List selectListOfOrganizationInfo(String deptId); + + /** + * + * 更新网格名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateGridByDeptId(String newDeptName, Long deptId); + + /** + * + * 批量更新话题表党员群名称 + * + * @params [groups] + * @return void + * @author liuchuang + * @since 2020/3/7 12:22 + */ + void updateBatchPartyGroupNameByGroupId(@Param("groups") List groups); + } diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/service/TopicService.java b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/service/TopicService.java index e8fc58120..7a9f3ed39 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/service/TopicService.java +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/service/TopicService.java @@ -20,12 +20,14 @@ package com.elink.esua.epdc.modules.topic.service; import com.elink.esua.epdc.commons.mybatis.service.BaseService; import com.elink.esua.epdc.commons.tools.page.PageData; import com.elink.esua.epdc.commons.tools.utils.Result; +import com.elink.esua.epdc.dto.group.GroupDTO; import com.elink.esua.epdc.dto.group.result.TopicAuditRecordResultDTO; import com.elink.esua.epdc.dto.topic.TopicDTO; import com.elink.esua.epdc.dto.topic.TopicDetailDTO; import com.elink.esua.epdc.dto.topic.form.*; import com.elink.esua.epdc.dto.topic.result.TopicDetailResultDTO; import com.elink.esua.epdc.dto.topic.result.TopicListResultDTO; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import com.elink.esua.epdc.modules.topic.entity.TopicEntity; import java.util.List; @@ -203,4 +205,26 @@ public interface TopicService extends BaseService { * @since 2019/11/12 10:24 */ TopicDetailDTO getDetail(String id); + + /** + * + * 话题修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); + + /** + * + * 更新话题表党员群名称 + * + * @params [groups] + * @return void + * @author liuchuang + * @since 2020/3/7 12:20 + */ + void modifyPartyGroupNameByGroupId(List groups); } diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/service/impl/TopicServiceImpl.java b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/service/impl/TopicServiceImpl.java index 50d05a905..e6944dd72 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/service/impl/TopicServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/java/com.elink.esua.epdc/modules/topic/service/impl/TopicServiceImpl.java @@ -53,6 +53,7 @@ import com.elink.esua.epdc.modules.comment.service.TopicCommentService; import com.elink.esua.epdc.modules.feign.EventFeignClient; import com.elink.esua.epdc.modules.group.service.GroupService; import com.elink.esua.epdc.modules.group.service.UserGroupService; +import com.elink.esua.epdc.modules.rocketmq.dto.OrganizationModifyDTO; import com.elink.esua.epdc.modules.topic.dao.TopicDao; import com.elink.esua.epdc.modules.topic.entity.GroupTopicUserReadEntity; import com.elink.esua.epdc.modules.topic.entity.TopicAuditRecordEntity; @@ -474,4 +475,66 @@ public class TopicServiceImpl extends BaseServiceImpl imp newsTask.insertUserInformation(topicUserNotice); } + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyOrganizationInfo(OrganizationModifyDTO dto) { + // 查询需要修改组织机构信息话题 + List topicList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != topicList && topicList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, topicList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + // 更新网格名称 + baseDao.updateGridByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, topicList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 2:14 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List topicList) { + List entities = new ArrayList<>(); + for (TopicDTO topic: topicList) { + TopicEntity entity = new TopicEntity(); + if (StringUtils.isNotEmpty(topic.getParentDeptIds()) && StringUtils.isNotEmpty(topic.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(topic.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(topic.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(topic.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(topic.getAllDeptIds()) && StringUtils.isNotEmpty(topic.getAllDeptNames())) { + List allDeptIds = Arrays.asList(topic.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(topic.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(topic.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyPartyGroupNameByGroupId(List groups) { + baseDao.updateBatchPartyGroupNameByGroupId(groups); + } + } diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/application.yml b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/application.yml index 4cb993330..99912f09d 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/application.yml +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/application.yml @@ -86,3 +86,8 @@ mybatis-plus: cache-enabled: false call-setters-on-nulls: true jdbc-type-for-null: 'null' + +rocketmq: + name-server: @rocketmq.name.server@ + consumer: + group: @rocketmq.consumer.group@ diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/mapper/group/GroupDao.xml b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/mapper/group/GroupDao.xml index b1eedcb0a..fa7ef629d 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/mapper/group/GroupDao.xml +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/mapper/group/GroupDao.xml @@ -389,4 +389,32 @@ ORDER BY and LORD_FLAG = 1 and DEL_FLAG = 0 + + + + + UPDATE epdc_group SET GRID = #{newDeptName}, UPDATED_TIME = NOW() WHERE GRID_ID = #{deptId} + + + diff --git a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/mapper/topic/TopicDao.xml b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/mapper/topic/TopicDao.xml index ee4ce9daf..3084f88a0 100644 --- a/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/mapper/topic/TopicDao.xml +++ b/esua-epdc/epdc-module/epdc-group/epdc-group-server/src/main/resources/mapper/topic/TopicDao.xml @@ -277,4 +277,28 @@ AND tp.ID = #{id} + + + + UPDATE epdc_topic SET GRID = #{newDeptName} WHERE GRID_ID = #{deptId} + + + + + UPDATE epdc_topic SET GROUP_NAME = #{group.groupName}, UPDATED_TIME = NOW() WHERE GROUP_ID = #{group.id} + + + + diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/pom.xml b/esua-epdc/epdc-module/epdc-news/epdc-news-server/pom.xml index b1711dd7f..a556cf4d0 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/pom.xml +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/pom.xml @@ -45,7 +45,12 @@ epdc-admin-client 1.0.0 - + + + org.apache.rocketmq + rocketmq-spring-boot-starter + 2.0.3 + @@ -126,6 +131,9 @@ false 47.104.224.45:8848 + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup @@ -150,6 +158,9 @@ true 47.104.224.45:8848 219.146.91.110 + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/BannerDao.java b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/BannerDao.java index b1aea43bd..f4ce1a582 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/BannerDao.java +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/BannerDao.java @@ -64,4 +64,26 @@ public interface BannerDao extends BaseDao { */ void updateSoltOut(String newsId); + /** + * + * 查询需要修改的组织机构信息 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 14:37 + */ + List selectListOfOrganizationInfo(String deptId); + + /** + * + * 更新部门名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateDeptNameByDeptId(String newDeptName, Long deptId); + } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/NewsDao.java b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/NewsDao.java index 6741982be..500237f86 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/NewsDao.java +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/NewsDao.java @@ -94,4 +94,26 @@ public interface NewsDao extends BaseDao { * @date 2020/2/1 11:00 */ List selectAllPage(Map params); + + /** + * + * 查询需要修改组织机构信息 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 14:44 + */ + List selectListOfOrganizationInfo(String deptId); + + /** + * + * 更新部门名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateDeptNameByDeptId(String newDeptName, Long deptId); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/NoticeDao.java b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/NoticeDao.java index 6f220a2d9..2b4340d73 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/NoticeDao.java +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/dao/NoticeDao.java @@ -87,4 +87,26 @@ public interface NoticeDao extends BaseDao { * @date 2020/2/1 11:28 */ List selectListByDeptId(Map params); + + /** + * + * 查询需要修改组织机构信息 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 14:54 + */ + List selectListOfOrganizationInfo(String deptId); + + /** + * + * 更新部门名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateDeptNameByDeptId(String newDeptName, Long deptId); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/rocketmq/consumer/OrganizationModifyConsumer.java b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/rocketmq/consumer/OrganizationModifyConsumer.java new file mode 100644 index 000000000..8cb6c92ad --- /dev/null +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/rocketmq/consumer/OrganizationModifyConsumer.java @@ -0,0 +1,57 @@ +package com.elink.esua.epdc.rocketmq.consumer; + +import com.alibaba.fastjson.JSONObject; +import com.elink.esua.epdc.commons.tools.constant.RocketMqConstant; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; +import com.elink.esua.epdc.service.BannerService; +import com.elink.esua.epdc.service.NewsService; +import com.elink.esua.epdc.service.NoticeService; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.MessageModel; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * 组织机构信息修改-监听MQ消息 + * + * @Author:liuchuang + * @Date:2020/3/7 13:44 + */ +@Slf4j +@Component +@RocketMQMessageListener(topic = RocketMqConstant.MQ_TOPIC_ORGANIZATION, consumerGroup = "${rocketmq.consumer.group}", messageModel = MessageModel.BROADCASTING) +public class OrganizationModifyConsumer implements RocketMQListener { + + @Autowired + private BannerService bannerService; + + @Autowired + private NewsService newsService; + + @Autowired + private NoticeService noticeService; + + @Override + public void onMessage(MessageExt messageExt) { + log.info("EPDC-NEWS-SERVER消费消息START:{topic:{}, msgId:{}}", RocketMqConstant.MQ_TOPIC_ORGANIZATION, messageExt.getMsgId()); + try { + String charset = "UTF-8"; + String body = new String(messageExt.getBody(), charset); + OrganizationModifyDTO dto = JSONObject.parseObject(body, OrganizationModifyDTO.class); + // banner表修改组织机构信息 + bannerService.modifyOrganizationInfo(dto); + // 新闻表修改组织机构信息 + newsService.modifyOrganizationInfo(dto); + // 通知表修改组织机构信息 + noticeService.modifyOrganizationInfo(dto); + log.info("EPDC-NEWS-SERVER消费消息END:{topic:{}, msgId:{}, body:{}}", RocketMqConstant.MQ_TOPIC_ORGANIZATION, messageExt.getMsgId(), body); + } catch (Exception e) { + log.info("EPDC-NEWS-SERVER消费消息失败:msgId:{}", messageExt.getMsgId()); + e.printStackTrace(); + } + } +} diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java new file mode 100644 index 000000000..9fc4a6170 --- /dev/null +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java @@ -0,0 +1,37 @@ +package com.elink.esua.epdc.rocketmq.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * + * 组织机构信息修改-接收MQ消息DTO + * + * @Author:liuchuang + * @Date:2020/3/7 13:43 + */ +@Data +public class OrganizationModifyDTO implements Serializable { + private static final long serialVersionUID = -5692602006311937083L; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 旧部门名称 + */ + private String oldDeptName; + + /** + * 新部门名称 + */ + private String newDeptName; + + /** + * 部门类型 + */ + private String typeKey; +} diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/BannerService.java b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/BannerService.java index ae4c8b193..a5846dd42 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/BannerService.java +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/BannerService.java @@ -24,6 +24,7 @@ import com.elink.esua.epdc.dto.BannerDTO; import com.elink.esua.epdc.dto.epdc.form.EpdcBannerListFromDTO; import com.elink.esua.epdc.dto.epdc.result.EpdcBannerListResultDTO; import com.elink.esua.epdc.entity.BannerEntity; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import java.util.List; import java.util.Map; @@ -131,4 +132,15 @@ public interface BannerService extends BaseService { * @date 2020/1/8 18:14 */ void updateSoltOut(String newsId); + + /** + * + * 修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/NewsService.java b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/NewsService.java index a22bf3787..93f96a33b 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/NewsService.java +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/NewsService.java @@ -28,6 +28,7 @@ import com.elink.esua.epdc.dto.epdc.form.EpdcNewsStatementFromDTO; import com.elink.esua.epdc.dto.epdc.result.EpdcNewsDetailResultDTO; import com.elink.esua.epdc.dto.epdc.result.EpdcNewsListResultDTO; import com.elink.esua.epdc.entity.NewsEntity; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import java.util.List; import java.util.Map; @@ -197,4 +198,15 @@ public interface NewsService extends BaseService { * @date 2020/2/1 10:48 */ PageData allPage(Map params); + + /** + * + * 修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/NoticeService.java b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/NoticeService.java index 2203e62d9..fd5dbcc3f 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/NoticeService.java +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/NoticeService.java @@ -26,6 +26,7 @@ import com.elink.esua.epdc.dto.epdc.form.EpdcNoticeListFormDTO; import com.elink.esua.epdc.dto.epdc.result.EpdcNoticeDetailResultDTO; import com.elink.esua.epdc.dto.epdc.result.EpdcNoticeListResultDTO; import com.elink.esua.epdc.entity.NoticeEntity; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import java.util.List; import java.util.Map; @@ -147,4 +148,15 @@ public interface NoticeService extends BaseService { * @date 2020/2/1 11:37 */ PageData pageForReadOnly(Map params); + + /** + * + * 修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/BannerServiceImpl.java b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/BannerServiceImpl.java index 4127e8be6..6364ff407 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/BannerServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/BannerServiceImpl.java @@ -38,6 +38,7 @@ import com.elink.esua.epdc.dto.epdc.form.EpdcBannerListFromDTO; import com.elink.esua.epdc.dto.epdc.result.EpdcBannerListResultDTO; import com.elink.esua.epdc.entity.BannerEntity; import com.elink.esua.epdc.feign.AdminFeignClient; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import com.elink.esua.epdc.service.BannerDepartmentService; import com.elink.esua.epdc.service.BannerService; import com.elink.esua.epdc.util.NewsUtils; @@ -185,4 +186,61 @@ public class BannerServiceImpl extends BaseServiceImpl bannerDTO.setState(YesOrNoEnum.NO.value()); baseDao.updateSoltOut(newsId); } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyOrganizationInfo(OrganizationModifyDTO dto) { + // 查询需要修改的组织机构信息 + List bannerList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != bannerList && bannerList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, bannerList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + + // 更新部门名称 + baseDao.updateDeptNameByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, bannerList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 14:41 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List bannerList) { + List entities = new ArrayList<>(); + for (BannerDTO banner: bannerList) { + BannerEntity entity = new BannerEntity(); + if (StringUtils.isNotEmpty(banner.getParentDeptIds()) && StringUtils.isNotEmpty(banner.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(banner.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(banner.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(banner.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(banner.getAllDeptIds()) && StringUtils.isNotEmpty(banner.getAllDeptNames())) { + List allDeptIds = Arrays.asList(banner.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(banner.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(banner.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/NewsServiceImpl.java b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/NewsServiceImpl.java index df024ab01..fb7bf42bb 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/NewsServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/NewsServiceImpl.java @@ -45,6 +45,7 @@ import com.elink.esua.epdc.dto.epdc.form.EpdcNewsStatementFromDTO; import com.elink.esua.epdc.dto.epdc.result.EpdcNewsDetailResultDTO; import com.elink.esua.epdc.entity.NewsEntity; import com.elink.esua.epdc.feign.AdminFeignClient; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import com.elink.esua.epdc.service.*; import com.elink.esua.epdc.util.NewsUtils; import org.apache.commons.lang3.StringUtils; @@ -52,10 +53,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Map; +import java.util.*; /** * 新闻表 @@ -487,4 +485,61 @@ public class NewsServiceImpl extends BaseServiceImpl implem List newsDaoList = baseDao.selectAllPage(params); return new PageData<>(newsDaoList, page.getTotal()); } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyOrganizationInfo(OrganizationModifyDTO dto) { + // 查询需要修改的组织机构信息 + List newsList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != newsList && newsList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, newsList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + + // 更新部门名称 + baseDao.updateDeptNameByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, newsList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 14:47 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List newsList) { + List entities = new ArrayList<>(); + for (NewsDTO news: newsList) { + NewsEntity entity = new NewsEntity(); + if (StringUtils.isNotEmpty(news.getParentDeptIds()) && StringUtils.isNotEmpty(news.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(news.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(news.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(news.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(news.getAllDeptIds()) && StringUtils.isNotEmpty(news.getAllDeptNames())) { + List allDeptIds = Arrays.asList(news.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(news.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(news.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/NoticeServiceImpl.java b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/NoticeServiceImpl.java index f4775d526..a95324054 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/NoticeServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/java/com/elink/esua/epdc/service/impl/NoticeServiceImpl.java @@ -40,6 +40,7 @@ import com.elink.esua.epdc.dto.epdc.result.EpdcNoticeListResultDTO; import com.elink.esua.epdc.entity.NoticeEntity; import com.elink.esua.epdc.feign.AdminFeignClient; import com.elink.esua.epdc.redis.NoticeRedis; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import com.elink.esua.epdc.service.NoticeDepartmentService; import com.elink.esua.epdc.service.NoticeService; import com.elink.esua.epdc.util.NewsUtils; @@ -228,4 +229,61 @@ public class NoticeServiceImpl extends BaseServiceImpl this.baseDao.updateReadingAmount(formDto.getNoticeId()); return new Result(); } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyOrganizationInfo(OrganizationModifyDTO dto) { + // 查询需要修改的组织机构信息 + List noticeList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != noticeList && noticeList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, noticeList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + + // 更新部门名称 + baseDao.updateDeptNameByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, noticeList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 14:56 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List noticeList) { + List entities = new ArrayList<>(); + for (NoticeDTO notice: noticeList) { + NoticeEntity entity = new NoticeEntity(); + if (StringUtils.isNotEmpty(notice.getParentDeptIds()) && StringUtils.isNotEmpty(notice.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(notice.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(notice.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(notice.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(notice.getAllDeptIds()) && StringUtils.isNotEmpty(notice.getAllDeptNames())) { + List allDeptIds = Arrays.asList(notice.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(notice.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(notice.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/application.yml b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/application.yml index d51d67bc6..f891a793a 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/application.yml +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/application.yml @@ -86,3 +86,8 @@ mybatis-plus: cache-enabled: false call-setters-on-nulls: true jdbc-type-for-null: 'null' + +rocketmq: + name-server: @rocketmq.name.server@ + consumer: + group: @rocketmq.consumer.group@ diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/BannerDao.xml b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/BannerDao.xml index 1a50a0bb8..be64882ba 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/BannerDao.xml +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/BannerDao.xml @@ -42,4 +42,21 @@ AND bn.DEL_FLAG = '0' + + + + UPDATE epdc_banner SET DEPT_NAME = #{newDeptName}, UPDATED_TIME = NOW() WHERE DEPT_ID = #{deptId} + + \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/NewsDao.xml b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/NewsDao.xml index 53ae1df68..db811eb64 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/NewsDao.xml +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/NewsDao.xml @@ -132,4 +132,21 @@ n.CREATED_TIME DESC + + + + + UPDATE epdc_news SET DEPT_NAME = #{newDeptName}, UPDATED_TIME = NOW() WHERE DEPT_ID = #{deptId} + \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/NoticeDao.xml b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/NoticeDao.xml index 6f7f5d09b..c87bd37fb 100644 --- a/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/NoticeDao.xml +++ b/esua-epdc/epdc-module/epdc-news/epdc-news-server/src/main/resources/mapper/NoticeDao.xml @@ -78,4 +78,21 @@ ORDER BY n.CREATED_TIME DESC + + + + UPDATE epdc_notice SET DEPT_NAME = #{newDeptName}, UPDATED_TIME = NOW() WHERE DEPT_ID = #{deptId} + + \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-client/src/main/java/com/elink/esua/epdc/dto/PartyAuthenticationFailedDTO.java b/esua-epdc/epdc-module/epdc-user/epdc-user-client/src/main/java/com/elink/esua/epdc/dto/PartyAuthenticationFailedDTO.java index feb2309db..0c06ad5d4 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-client/src/main/java/com/elink/esua/epdc/dto/PartyAuthenticationFailedDTO.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-client/src/main/java/com/elink/esua/epdc/dto/PartyAuthenticationFailedDTO.java @@ -158,8 +158,20 @@ public class PartyAuthenticationFailedDTO implements Serializable { */ private String address; - /*** - *父所有部门 + /** + * 父所有部门ID + */ + private String parentDeptIds; + /** + * 父所有部门名称 + */ + private String parentDeptNames; + /** + * 所有部门ID + */ + private String allDeptIds; + /** + * 所有部门名称 */ private String allDeptNames; diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-client/src/main/java/com/elink/esua/epdc/dto/PartyMembersDTO.java b/esua-epdc/epdc-module/epdc-user/epdc-user-client/src/main/java/com/elink/esua/epdc/dto/PartyMembersDTO.java index 6a1b156ee..1c61109ea 100755 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-client/src/main/java/com/elink/esua/epdc/dto/PartyMembersDTO.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-client/src/main/java/com/elink/esua/epdc/dto/PartyMembersDTO.java @@ -95,4 +95,17 @@ public class PartyMembersDTO implements Serializable { private String partyOrganization; + /** + * 父所有部门ID + */ + private String parentDeptIds; + /** + * 父所有部门名称 + */ + private String parentDeptNames; + /** + * 所有部门ID + */ + private String allDeptIdsStr; + } diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/pom.xml b/esua-epdc/epdc-module/epdc-user/epdc-user-server/pom.xml index 674ee49bb..2e875c817 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/pom.xml +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/pom.xml @@ -55,6 +55,12 @@ spring-boot-admin-starter-client ${spring.boot.admin.version} + + + org.apache.rocketmq + rocketmq-spring-boot-starter + 2.0.3 + @@ -141,6 +147,9 @@ false 47.104.224.45:8848 + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup @@ -171,6 +180,9 @@ true 47.104.224.45:8848 219.146.91.110 + + 47.104.85.99:9876;114.215.125.123:9876 + organizationGroup diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/PartyAuthenticationFailedDao.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/PartyAuthenticationFailedDao.java index 352315cb0..aa3690901 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/PartyAuthenticationFailedDao.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/PartyAuthenticationFailedDao.java @@ -42,4 +42,26 @@ public interface PartyAuthenticationFailedDao extends BaseDao selectListDto(Map params); + + /** + * + * 查询需要修改的组织机构信息 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 15:31 + */ + List selectListOfOrganizationInfo(String deptId); + + /** + * + * 更新网格名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateGridByDeptId(String newDeptName, Long deptId); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/PartyMembersDao.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/PartyMembersDao.java index ed047ccfa..3d422439c 100755 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/PartyMembersDao.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/PartyMembersDao.java @@ -40,4 +40,26 @@ public interface PartyMembersDao extends BaseDao { PartyMembersDTO selectByIdNew(String id); List hasAuthenticationPartyPage(Map params); + + /** + * + * 查询需要修改的组织机构信息 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 15:31 + */ + List selectListOfOrganizationInfo(String deptId); + + /** + * + * 更新网格名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateGridByDeptId(String newDeptName, Long deptId); } diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserDao.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserDao.java index 8567fe190..e53bb438b 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserDao.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserDao.java @@ -177,4 +177,15 @@ public interface UserDao extends BaseDao { * @date 2020/2/25 13:54 */ List selectListUserByWxForLogin(@Param("wxOpenId") String wxOpenId, @Param("wxUnionId") String wxUnionId); + + /** + * + * 查询需要修改的组织机构信息 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 15:31 + */ + List selectListOfOrganizationInfo(String deptId); } diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserGridRelationDao.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserGridRelationDao.java index d6886cad3..cb3a4041c 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserGridRelationDao.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserGridRelationDao.java @@ -22,6 +22,8 @@ import com.elink.esua.epdc.dto.UserGridRelationDTO; import com.elink.esua.epdc.entity.UserGridRelationEntity; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * 网格长与网格关系表 * @@ -42,4 +44,26 @@ public interface UserGridRelationDao extends BaseDao { * @since 2019/12/6 10:45 */ UserGridRelationDTO selectOneOfGird(String userId); + + /** + * + * 查询需要修改的组织机构信息 + * + * @params [deptId] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 15:31 + */ + List selectListOfOrganizationInfo(String deptId); + + /** + * + * 更新网格名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateGridByDeptId(String newDeptName, Long deptId); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserInvitationRecordDao.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserInvitationRecordDao.java index 9468758c2..cfcba25c9 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserInvitationRecordDao.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/dao/UserInvitationRecordDao.java @@ -43,5 +43,16 @@ public interface UserInvitationRecordDao extends BaseDao invitationRecord(@Param("userId") Long userId); + + /** + * + * 更新网格名称 + * + * @params [newDeptName, deptId] + * @return void + * @author liuchuang + * @since 2020/3/7 1:20 + */ + void updateGridByDeptId(String newDeptName, Long deptId); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/rocketmq/consumer/OrganizationModifyConsumer.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/rocketmq/consumer/OrganizationModifyConsumer.java new file mode 100644 index 000000000..b8ef0d0f0 --- /dev/null +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/rocketmq/consumer/OrganizationModifyConsumer.java @@ -0,0 +1,65 @@ +package com.elink.esua.epdc.rocketmq.consumer; + +import com.alibaba.fastjson.JSONObject; +import com.elink.esua.epdc.commons.tools.constant.RocketMqConstant; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; +import com.elink.esua.epdc.service.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.MessageModel; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * 组织机构信息修改-监听MQ消息 + * + * @Author:liuchuang + * @Date:2020/3/7 13:47 + */ +@Slf4j +@Component +@RocketMQMessageListener(topic = RocketMqConstant.MQ_TOPIC_ORGANIZATION, consumerGroup = "${rocketmq.consumer.group}", messageModel = MessageModel.BROADCASTING) +public class OrganizationModifyConsumer implements RocketMQListener { + + @Autowired + private PartyAuthenticationFailedService partyAuthenticationFailedService; + + @Autowired + private PartyMembersService partyMembersService; + + @Autowired + private UserService userService; + + @Autowired + private UserGridRelationService userGridRelationService; + + @Autowired + private UserInvitationRecordService userInvitationRecordService; + + @Override + public void onMessage(MessageExt messageExt) { + log.info("EPDC-USER-SERVER消费消息START:{topic:{}, msgId:{}}", RocketMqConstant.MQ_TOPIC_ORGANIZATION, messageExt.getMsgId()); + try { + String charset = "UTF-8"; + String body = new String(messageExt.getBody(), charset); + OrganizationModifyDTO dto = JSONObject.parseObject(body, OrganizationModifyDTO.class); + // 党员认证失败表修改组织机构信息 + partyAuthenticationFailedService.modifyOrganizationInfo(dto); + // 党员表修改组织机构信息 + partyMembersService.modifyOrganizationInfo(dto); + // 用户表修改组织机构信息 + userService.modifyOrganizationInfo(dto); + // 用户网格关系表修改组织机构信息 + userGridRelationService.modifyOrganizationInfo(dto); + // 用户邀请记录表修改组织机构信息 + userInvitationRecordService.modifyOrganizationInfo(dto); + log.info("EPDC-USER-SERVER消费消息END:{topic:{}, msgId:{}, body:{}}", RocketMqConstant.MQ_TOPIC_ORGANIZATION, messageExt.getMsgId(), body); + } catch (Exception e) { + log.info("EPDC-USER-SERVER消费消息失败:msgId:{}", messageExt.getMsgId()); + e.printStackTrace(); + } + } +} diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java new file mode 100644 index 000000000..636d7b744 --- /dev/null +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/rocketmq/dto/OrganizationModifyDTO.java @@ -0,0 +1,37 @@ +package com.elink.esua.epdc.rocketmq.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * + * 组织机构信息修改-接收MQ消息DTO + * + * @Author:liuchuang + * @Date:2020/3/7 13:46 + */ +@Data +public class OrganizationModifyDTO implements Serializable { + private static final long serialVersionUID = -5692602006311937083L; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 旧部门名称 + */ + private String oldDeptName; + + /** + * 新部门名称 + */ + private String newDeptName; + + /** + * 部门类型 + */ + private String typeKey; +} diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/PartyAuthenticationFailedService.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/PartyAuthenticationFailedService.java index 3901c8c7d..63d50a8e8 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/PartyAuthenticationFailedService.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/PartyAuthenticationFailedService.java @@ -21,6 +21,7 @@ import com.elink.esua.epdc.commons.mybatis.service.BaseService; import com.elink.esua.epdc.commons.tools.page.PageData; import com.elink.esua.epdc.dto.PartyAuthenticationFailedDTO; import com.elink.esua.epdc.entity.PartyAuthenticationFailedEntity; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import java.util.List; import java.util.Map; @@ -92,4 +93,15 @@ public interface PartyAuthenticationFailedService extends BaseService { * @date 2020/2/16 16:18 */ Result upDataInfo(List userEntities); + + /** + * + * 事件修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/UserGridRelationService.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/UserGridRelationService.java index 65df6d8ee..c40097472 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/UserGridRelationService.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/UserGridRelationService.java @@ -25,6 +25,7 @@ import com.elink.esua.epdc.dto.epdc.form.EpdcAppRemoveGridFormDTO; import com.elink.esua.epdc.dto.epdc.form.EpdcLeaderSwitchGridFormDTO; import com.elink.esua.epdc.dto.epdc.result.EpdcUserGridResultDTO; import com.elink.esua.epdc.entity.UserGridRelationEntity; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import java.util.List; import java.util.Map; @@ -176,4 +177,15 @@ public interface UserGridRelationService extends BaseService invitationRecord(Long userId); + + /** + * + * 事件修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/UserService.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/UserService.java index 07da036b7..30c7e0227 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/UserService.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/UserService.java @@ -32,6 +32,7 @@ import com.elink.esua.epdc.dto.epdc.result.EpdcUserGroupInviteResultDTO; import com.elink.esua.epdc.dto.epdc.result.*; import com.elink.esua.epdc.dto.epdc.result.EpdcWorkUserResultDTO; import com.elink.esua.epdc.entity.UserEntity; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import org.springframework.web.multipart.MultipartFile; import java.util.List; @@ -296,4 +297,15 @@ public interface UserService extends BaseService { * @date 2020/2/28 13:44 */ Result completeRequisiteInfo(CompleteRequisiteUserInfoDTO fromDto); + + /** + * + * 事件修改组织机构信息 + * + * @params [dto] + * @return void + * @author liuchuang + * @since 2020/3/7 1:23 + */ + void modifyOrganizationInfo(OrganizationModifyDTO dto); } diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/PartyAuthenticationFailedServiceImpl.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/PartyAuthenticationFailedServiceImpl.java index 49f92ba65..f1614a0f7 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/PartyAuthenticationFailedServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/PartyAuthenticationFailedServiceImpl.java @@ -27,12 +27,15 @@ import com.elink.esua.epdc.dao.PartyAuthenticationFailedDao; import com.elink.esua.epdc.datasources.DataSourceNames; import com.elink.esua.epdc.dto.PartyAuthenticationFailedDTO; import com.elink.esua.epdc.entity.PartyAuthenticationFailedEntity; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import com.elink.esua.epdc.service.PartyAuthenticationFailedService; import com.elink.esua.epdc.util.AppUserUtils; import com.google.common.collect.Lists; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -104,4 +107,61 @@ public class PartyAuthenticationFailedServiceImpl extends BaseServiceImpl partyList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != partyList && partyList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, partyList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + + // 更新网格名称 + baseDao.updateGridByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, partyList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 15:13 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List partyList) { + List entities = new ArrayList<>(); + for (PartyAuthenticationFailedDTO party: partyList) { + PartyAuthenticationFailedEntity entity = new PartyAuthenticationFailedEntity(); + if (StringUtils.isNotEmpty(party.getParentDeptIds()) && StringUtils.isNotEmpty(party.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(party.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(party.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(party.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(party.getAllDeptIds()) && StringUtils.isNotEmpty(party.getAllDeptNames())) { + List allDeptIds = Arrays.asList(party.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(party.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(party.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } + } \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/PartyMembersServiceImpl.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/PartyMembersServiceImpl.java index a1c8f3e8f..9d2d4a082 100755 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/PartyMembersServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/PartyMembersServiceImpl.java @@ -45,6 +45,7 @@ import com.elink.esua.epdc.entity.UserEntity; import com.elink.esua.epdc.enums.PartyMemberRegFlagEnum; import com.elink.esua.epdc.excel.PartyMembersExcel; import com.elink.esua.epdc.feign.AdminFeignClient; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import com.elink.esua.epdc.service.PartyMembersService; import com.elink.esua.epdc.service.PartyTagRelationService; import com.elink.esua.epdc.util.AppUserUtils; @@ -427,4 +428,61 @@ public class PartyMembersServiceImpl extends BaseServiceImpl partyList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != partyList && partyList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, partyList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + + // 更新网格名称 + baseDao.updateGridByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, partyList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 15:17 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List partyList) { + List entities = new ArrayList<>(); + for (PartyMembersDTO party: partyList) { + PartyMembersEntity entity = new PartyMembersEntity(); + if (StringUtils.isNotEmpty(party.getParentDeptIds()) && StringUtils.isNotEmpty(party.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(party.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(party.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(party.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(party.getAllDeptIdsStr()) && StringUtils.isNotEmpty(party.getAllDeptNames())) { + List allDeptIds = Arrays.asList(party.getAllDeptIdsStr().split(",")); + List allDeptNames = Arrays.asList(party.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(party.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } } diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/UserGridRelationServiceImpl.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/UserGridRelationServiceImpl.java index 7ddb09848..76a976352 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/UserGridRelationServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/UserGridRelationServiceImpl.java @@ -34,16 +34,14 @@ import com.elink.esua.epdc.dto.epdc.form.EpdcAppRemoveGridFormDTO; import com.elink.esua.epdc.dto.epdc.form.EpdcLeaderSwitchGridFormDTO; import com.elink.esua.epdc.dto.epdc.result.EpdcUserGridResultDTO; import com.elink.esua.epdc.entity.UserGridRelationEntity; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import com.elink.esua.epdc.service.UserGridRelationService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Map; +import java.util.*; /** * 网格长与网格关系表 @@ -218,4 +216,61 @@ public class UserGridRelationServiceImpl extends BaseServiceImpl gridList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != gridList && gridList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, gridList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + + // 更新网格名称 + baseDao.updateGridByDeptId(dto.getNewDeptName(), dto.getDeptId()); + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, gridList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 15:25 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List gridList) { + List entities = new ArrayList<>(); + for (UserGridRelationDTO grid: gridList) { + UserGridRelationEntity entity = new UserGridRelationEntity(); + if (StringUtils.isNotEmpty(grid.getParentDeptIds()) && StringUtils.isNotEmpty(grid.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(grid.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(grid.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(grid.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(grid.getAllDeptIds()) && StringUtils.isNotEmpty(grid.getAllDeptNames())) { + List allDeptIds = Arrays.asList(grid.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(grid.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(grid.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } } diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/UserInvitationRecordServiceImpl.java b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/UserInvitationRecordServiceImpl.java index 86c9a771c..9902181d1 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/UserInvitationRecordServiceImpl.java +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/java/com/elink/esua/epdc/service/impl/UserInvitationRecordServiceImpl.java @@ -28,12 +28,14 @@ import com.elink.esua.epdc.dto.UserInvitationRecordDTO; import com.elink.esua.epdc.dto.epdc.result.UserInvitationRecordResultDTO; import com.elink.esua.epdc.entity.UserInvitationRecordEntity; import com.elink.esua.epdc.redis.UserInvitationRecordRedis; +import com.elink.esua.epdc.rocketmq.dto.OrganizationModifyDTO; import com.elink.esua.epdc.service.UserInvitationRecordService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -106,4 +108,11 @@ public class UserInvitationRecordServiceImpl extends BaseServiceImpl implem baseDao.updateById(updateUser); return new Result(); } + + @Override + @Transactional(rollbackFor = Exception.class) + public void modifyOrganizationInfo(OrganizationModifyDTO dto) { + // 查询需要修改的组织机构信息 + List userList = baseDao.selectListOfOrganizationInfo(dto.getDeptId().toString()); + if (null != userList && userList.size() > 0) { + // 组织机构信息处理 + List entities = handleOrganizationInfo(dto, userList); + // 更新事件组织机构信息 + updateBatchById(entities); + } + } + + /** + * + * 组织机构信息处理 + * + * @params [dto, userList] + * @return java.util.List + * @author liuchuang + * @since 2020/3/7 15:22 + */ + private List handleOrganizationInfo(OrganizationModifyDTO dto, List userList) { + List entities = new ArrayList<>(); + for (UserDTO user: userList) { + UserEntity entity = new UserEntity(); + if (StringUtils.isNotEmpty(user.getParentDeptIds()) && StringUtils.isNotEmpty(user.getParentDeptNames())) { + List parentDeptIds = Arrays.asList(user.getParentDeptIds().split(",")); + List parentDeptNames = Arrays.asList(user.getParentDeptNames().split("-")); + int index = parentDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && parentDeptNames.size() > index) { + parentDeptNames.set(index, dto.getNewDeptName()); + entity.setId(user.getId()); + entity.setParentDeptNames(StringUtils.join(parentDeptNames, "-")); + } + } + + if (StringUtils.isNotEmpty(user.getAllDeptIds()) && StringUtils.isNotEmpty(user.getAllDeptNames())) { + List allDeptIds = Arrays.asList(user.getAllDeptIds().split(",")); + List allDeptNames = Arrays.asList(user.getAllDeptNames().split("-")); + int index = allDeptIds.indexOf(dto.getDeptId().toString()); + if (index >= 0 && allDeptNames.size() > index) { + allDeptNames.set(index, dto.getNewDeptName()); + entity.setId(user.getId()); + entity.setAllDeptNames(StringUtils.join(allDeptNames, "-")); + } + } + + entities.add(entity); + } + + return entities; + } } diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/application.yml b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/application.yml index 0f01ce17c..72b41c505 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/application.yml +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/application.yml @@ -92,3 +92,8 @@ mybatis-plus: cache-enabled: false call-setters-on-nulls: true jdbc-type-for-null: 'null' + +rocketmq: + name-server: @rocketmq.name.server@ + consumer: + group: @rocketmq.consumer.group@ diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/PartyAuthenticationFailedDao.xml b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/PartyAuthenticationFailedDao.xml index 3655396bf..1d3aa5f89 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/PartyAuthenticationFailedDao.xml +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/PartyAuthenticationFailedDao.xml @@ -55,5 +55,21 @@ epaf.CREATED_TIME desc + + + + UPDATE epdc_party_authentication_failed SET GRID_NAME = #{newDeptName}, UPDATED_TIME = NOW() WHERE GRID_ID = #{deptId} + \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/PartyMembersDao.xml b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/PartyMembersDao.xml index 66859b4fe..535ddb8da 100755 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/PartyMembersDao.xml +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/PartyMembersDao.xml @@ -137,5 +137,21 @@ pm.ID; + + + + UPDATE epdc_party_members SET GRID_NAME = #{newDeptName}, UPDATED_TIME = NOW() WHERE GRID_ID = #{deptId} + diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserDao.xml b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserDao.xml index b9b7250c1..84f7768f2 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserDao.xml +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserDao.xml @@ -396,4 +396,17 @@ ur.SWITCHED_TIME DESC + + diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserGridRelationDao.xml b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserGridRelationDao.xml index f09ba43d4..722d56e33 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserGridRelationDao.xml +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserGridRelationDao.xml @@ -16,4 +16,21 @@ LIMIT 1 + + + + UPDATE epdc_user_grid_relation SET GRID = #{newDeptName}, UPDATED_TIME = NOW() WHERE GRID_ID = #{deptId} + + \ No newline at end of file diff --git a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserInvitationRecordDao.xml b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserInvitationRecordDao.xml index 16ba7ae21..bbafa7efe 100644 --- a/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserInvitationRecordDao.xml +++ b/esua-epdc/epdc-module/epdc-user/epdc-user-server/src/main/resources/mapper/UserInvitationRecordDao.xml @@ -41,5 +41,8 @@ AND record.INVITE_USER_ID =#{userId} + + UPDATE epdc_user_invitation_record SET GRID = #{newDeptName}, UPDATED_TIME = NOW() WHERE GRID_ID = #{deptId} + \ No newline at end of file