From 986675e73b4095c9f51459c731804df6eaba0854 Mon Sep 17 00:00:00 2001 From: JuanC Galvis <8420868+juancgalvis@users.noreply.github.com> Date: Wed, 7 Feb 2024 09:52:57 -0500 Subject: [PATCH] feat(multi-qmgr): Enable multi queue manager and reques reply for fixed queues (#35) * Upgrade annotations, enable multiple broker connections, encapsulate request reply for fixed queues with selector listener --- .gitignore | 2 + README.md | 187 +++++----------- .../jms/api/MQDomainMessageSender.java | 17 ++ .../commons/jms/api/MQMessageSender.java | 3 +- .../commons/jms/api/MQQueueManagerSetter.java | 1 + .../commons/jms/api/MQRequestReply.java | 2 +- ...ableReqReply.java => EnableMQGateway.java} | 9 +- .../commons/jms/mq/EnableMQMessageSender.java | 13 -- .../mq/EnableMQSelectorMessageListener.java | 13 -- .../commons/jms/mq/MQListener.java | 29 ++- .../commons/jms/mq/MQListeners.java | 6 +- .../bancolombia/commons/jms/mq/MQSender.java | 63 ++++++ .../bancolombia/commons/jms/mq/ReqReply.java | 84 +++++-- .../config/MQAnnotationAutoconfiguration.java | 44 ++++ .../jms/mq/config/MQAutoconfiguration.java | 83 ++++++- .../MQAutoconfigurationSelectorListener.java | 118 ---------- .../mq/config/MQAutoconfigurationSender.java | 74 ------- .../config/MQListenerAnnotationProcessor.java | 143 ------------ .../config/MQListenerAutoconfiguration.java | 18 ++ .../commons/jms/mq/config/MQProperties.java | 25 ++- .../jms/mq/config/MQSpringResolver.java | 105 +++++++++ .../mq/config/factory/MQListenerFactory.java | 138 ++++++++++++ .../mq/config/factory/MQReqReplyFactory.java | 178 +++++++++++++++ .../mq/config/factory/MQSenderFactory.java | 95 ++++++++ .../model/AnnotationSenderSettings.java | 43 ++++ .../health/MQListenerHealthIndicator.java | 2 +- .../config/proxy/EnableReqReplyRegistrar.java | 37 ---- .../InterfaceComponentProxyFactoryBean.java | 209 ------------------ .../senders/MQAutoconfigurationSender.java | 83 +++++++ .../mq/config/senders/MQSenderContainer.java | 25 +++ .../jms/mq/config/utils/AnnotationParser.java | 43 ++++ .../jms/mq/config/utils/AnnotationUtils.java | 12 +- .../MQBeanScanner.java} | 32 ++- .../jms/mq/config/utils/MQFactoryBean.java | 57 +++++ .../jms/mq/listeners/MQExecutorService.java | 11 + .../jms/mq/listeners/MQMessageListener.java | 4 +- .../listeners/MQMessageListenerRetries.java | 5 +- .../listeners/MQReactiveMessageListener.java | 4 +- .../mq/listeners/MQRequestReplyListener.java | 8 +- .../mq/listeners/MQRequestReplySelector.java | 75 +++++++ .../commons/jms/mq/utils/MQUtils.java | 8 +- .../MQAnnotationAutoconfigurationTest.java | 27 +++ .../mq/config/MQAutoconfiguracionTest.java | 78 ++++++- ...AutoconfigurationSelectorListenerTest.java | 121 ---------- ...a => MQListenerAutoconfigurationTest.java} | 73 +++--- ...eanTest.java => MQSpringResolverTest.java} | 125 ++++++----- .../health/MQListenerHealthIndicatorTest.java | 3 +- .../proxy/EnableReqReplyRegistrarTest.java | 34 --- .../jms/mq/config/proxy/SampleConfig.java | 9 - .../MQAutoconfigurationSenderTest.java | 77 +++++++ .../config/senders/MQSenderContainerTest.java | 68 ++++++ .../mq/config/utils/AnnotationParserTest.java | 67 ++++++ .../mq/config/utils/AnnotationUtilsTest.java | 9 +- .../MQBeanScannerTest.java} | 17 +- .../mq/config/utils/MQFactoryBeanTest.java | 133 +++++++++++ .../jms/mq/config/{proxy => utils}/Utils.java | 21 +- .../mq/config/utils/sample/FixedReqReply.java | 26 +++ .../mq/config/utils/sample/SampleConfig.java | 9 + .../mq/config/utils/sample/SampleSender.java | 24 ++ .../sample/TestReqReply.java} | 9 +- .../commons/jms/mq/helper/JmsContextImpl.java | 4 +- .../mq/listeners/MQMessageListenerTest.java | 5 +- .../MQReactiveMessageListenerTest.java | 19 +- .../listeners/MQRequestReplyListenerTest.java | 14 +- .../listeners/MQRequestReplySelectorTest.java | 108 +++++++++ .../commons/jms/mq/utils/MQUtilsTest.java | 9 +- .../internal/listener/MQContextListener.java | 35 ++- .../MQContextMessageSelectorListenerSync.java | 11 +- ...ltiContextMessageSelectorListenerSync.java | 30 +-- .../selector/strategy/SelectorBuilder.java | 9 + .../jms/internal/models/MQListenerConfig.java | 26 ++- .../jms/internal/models/MQReqReplyConfig.java | 41 ++++ .../jms/internal/models/MQSenderConfig.java | 19 ++ .../internal/sender/MQContextSenderSync.java | 15 +- .../sender/MQDomainContextSender.java | 30 +++ .../internal/sender/MQMultiContextSender.java | 3 +- .../sender/MQMultiContextSenderSync.java | 45 ++-- .../jms/utils/MQMessageListenerUtils.java | 16 +- .../commons/jms/utils/MQQueueUtils.java | 6 +- .../jms/utils/ReactiveReplyRouter.java | 1 + .../listener/MQContextListenerTest.java | 8 +- .../MQContextTemporaryListenerTest.java | 13 +- ...ontextMessageSelectorListenerSyncTest.java | 59 +++-- ...ltiContextMessageSelectorListenerTest.java | 10 +- .../AbstractJMSReconnectableTest.java | 3 +- .../sender/MQMultiContextSenderSyncTest.java | 24 +- .../sender/MQMultiContextSenderTest.java | 4 +- .../jms/utils/MQMessageListenerUtilsTest.java | 39 ++-- .../commons/jms/utils/MQQueueUtilsTest.java | 12 +- .../jms/utils/MQQueuesContainerImpTest.java | 25 ++- .../jms/utils/ReactiveReplyRouterTest.java | 6 + .../commons/jms/utils/RetryableTaskTest.java | 34 +++ .../noreactive}/app/MainApplication.java | 2 +- .../sample/noreactive}/app/config/Config.java | 2 +- .../noreactive/app/config/UseCasesConfig.java | 2 +- .../exceptions/ParseMessageException.java | 2 +- .../RelatedMessageNotFoundException.java | 2 +- .../noreactive}/domain/model/Request.java | 2 +- .../domain/model/RequestGateway.java | 2 +- .../noreactive}/domain/model/Result.java | 2 +- .../domain/usecase/ReplyRouterUseCase.java | 6 +- .../domain/usecase/SampleUseCase.java | 8 +- .../noreactive/drivenadapters/MyMQSender.java | 12 +- .../noreactive/entrypoints/MyMQListener.java | 14 +- .../sample/noreactive/entrypoints/Rest.java | 6 +- .../src/main/resources/application.yaml | 1 - examples/mq-reactive-replier/README.md | 1 + .../jms/replier/app/config/Config.java | 28 --- .../jms/replier/entrypoints/MyMQListener.java | 36 --- .../sample/replier}/app/MainApplication.java | 2 +- .../sample/replier/app/config/Config.java | 74 +++++++ .../replier/app/config/UseCasesConfig.java | 2 +- .../replier/domain/model/Request.java | 2 +- .../replier/domain/model/Result.java | 2 +- .../replier/drivenadapters/XDomainSender.java | 8 + .../replier/entrypoints/MyMQListener.java | 52 +++++ .../src/main/resources/application.yaml | 3 +- .../sample/selector}/app/MainApplication.java | 2 +- .../sample/selector}/app/config/Config.java | 2 +- .../selector/app/config/UseCasesConfig.java | 2 +- .../exceptions/ParseMessageException.java | 2 +- .../selector}/domain/model/Request.java | 2 +- .../selector/domain/model/RequestGateway.java | 2 +- .../sample/selector}/domain/model/Result.java | 2 +- .../domain/usecase/SampleUseCase.java | 8 +- .../selector/drivenadapters/MyMQSender.java | 16 +- .../sample/selector/entrypoints/Rest.java | 6 +- .../src/main/resources/application.yaml | 1 - examples/mq-reactive/README.md | 1 + examples/mq-reactive/mq-reactive.gradle | 1 + .../jms/sample/app/config/Config.java | 39 ---- .../reqreply/MyRequestReply.java | 11 - .../sample}/app/MainApplication.java | 4 +- .../bancolombia/sample/app/config/Config.java | 85 +++++++ .../sample/app/config/UseCasesConfig.java | 2 +- .../exceptions/ParseMessageException.java | 2 +- .../RelatedMessageNotFoundException.java | 2 +- .../sample/domain/model/Request.java | 2 +- .../sample/domain/model/RequestGateway.java | 3 +- .../{jms => }/sample/domain/model/Result.java | 2 +- .../sample/domain/model/SenderGateway.java | 2 +- .../domain/usecase/SampleReqReplyUseCase.java | 16 +- .../sample/domain/usecase/SampleUseCase.java | 8 +- .../sample/drivenadapters/MyMQSender.java | 19 +- .../sample/drivenadapters/XDomainSender.java | 8 + .../reqreply/MyRequestReply.java | 10 + .../reqreply/MyRequestReplyAdapter.java | 26 ++- .../reqreply/MyRequestReplyTmp.java | 8 + .../sample/entrypoints/MyMQListener.java | 14 +- .../{jms => }/sample/entrypoints/Rest.java | 20 +- .../src/main/resources/application.yaml | 7 +- main.gradle | 6 +- 152 files changed, 2790 insertions(+), 1547 deletions(-) create mode 100644 commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQDomainMessageSender.java rename commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/{EnableReqReply.java => EnableMQGateway.java} (66%) delete mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableMQMessageSender.java delete mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableMQSelectorMessageListener.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQSender.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAnnotationAutoconfiguration.java delete mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSelectorListener.java delete mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSender.java delete mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAnnotationProcessor.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAutoconfiguration.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQSpringResolver.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQListenerFactory.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQReqReplyFactory.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQSenderFactory.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/model/AnnotationSenderSettings.java delete mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/proxy/EnableReqReplyRegistrar.java delete mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/proxy/InterfaceComponentProxyFactoryBean.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/senders/MQAutoconfigurationSender.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/senders/MQSenderContainer.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationParser.java rename commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/{proxy/ReqReplyBeanScanner.java => utils/MQBeanScanner.java} (50%) create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/MQFactoryBean.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQExecutorService.java create mode 100644 commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplySelector.java create mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAnnotationAutoconfigurationTest.java delete mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSelectorListenerTest.java rename commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/{MQListenerAnnotationProcessorTest.java => MQListenerAutoconfigurationTest.java} (65%) rename commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/{proxy/InterfaceComponentProxyFactoryBeanTest.java => MQSpringResolverTest.java} (51%) delete mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/EnableReqReplyRegistrarTest.java delete mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/SampleConfig.java create mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/senders/MQAutoconfigurationSenderTest.java create mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/senders/MQSenderContainerTest.java create mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationParserTest.java rename commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/{proxy/ReqReplyBeanScannerTest.java => utils/MQBeanScannerTest.java} (61%) create mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/MQFactoryBeanTest.java rename commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/{proxy => utils}/Utils.java (54%) create mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/FixedReqReply.java create mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/SampleConfig.java create mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/SampleSender.java rename commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/{proxy/TestCustomAnnotation.java => utils/sample/TestReqReply.java} (77%) create mode 100644 commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplySelectorTest.java create mode 100644 commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/selector/strategy/SelectorBuilder.java create mode 100644 commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQReqReplyConfig.java create mode 100644 commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQSenderConfig.java create mode 100644 commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQDomainContextSender.java create mode 100644 commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/RetryableTaskTest.java rename examples/{mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector => mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive}/app/MainApplication.java (86%) rename examples/{mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector => mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive}/app/config/Config.java (83%) rename examples/mq-mvc-app/src/main/java/co/com/bancolombia/{jms => }/sample/noreactive/app/config/UseCasesConfig.java (88%) rename examples/{mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector => mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive}/domain/exceptions/ParseMessageException.java (68%) rename examples/mq-mvc-app/src/main/java/co/com/bancolombia/{jms => }/sample/noreactive/domain/exceptions/RelatedMessageNotFoundException.java (52%) rename examples/{mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector => mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive}/domain/model/Request.java (79%) rename examples/mq-mvc-app/src/main/java/co/com/bancolombia/{jms => }/sample/noreactive/domain/model/RequestGateway.java (52%) rename examples/{mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector => mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive}/domain/model/Result.java (80%) rename examples/mq-mvc-app/src/main/java/co/com/bancolombia/{jms => }/sample/noreactive/domain/usecase/ReplyRouterUseCase.java (82%) rename examples/mq-mvc-app/src/main/java/co/com/bancolombia/{jms => }/sample/noreactive/domain/usecase/SampleUseCase.java (69%) rename examples/mq-mvc-app/src/main/java/co/com/bancolombia/{jms => }/sample/noreactive/drivenadapters/MyMQSender.java (67%) rename examples/mq-mvc-app/src/main/java/co/com/bancolombia/{jms => }/sample/noreactive/entrypoints/MyMQListener.java (80%) rename examples/mq-mvc-app/src/main/java/co/com/bancolombia/{jms => }/sample/noreactive/entrypoints/Rest.java (66%) delete mode 100644 examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/app/config/Config.java delete mode 100644 examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/entrypoints/MyMQListener.java rename examples/{mq-reactive/src/main/java/co/com/bancolombia/jms/sample => mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier}/app/MainApplication.java (87%) create mode 100644 examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/app/config/Config.java rename examples/mq-reactive-replier/src/main/java/co/com/bancolombia/{jms => sample}/replier/app/config/UseCasesConfig.java (89%) rename examples/mq-reactive-replier/src/main/java/co/com/bancolombia/{jms => sample}/replier/domain/model/Request.java (81%) rename examples/mq-reactive-replier/src/main/java/co/com/bancolombia/{jms => sample}/replier/domain/model/Result.java (81%) create mode 100644 examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/drivenadapters/XDomainSender.java create mode 100644 examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/entrypoints/MyMQListener.java rename examples/{mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier => mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector}/app/MainApplication.java (87%) rename examples/{mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive => mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector}/app/config/Config.java (83%) rename examples/mq-reactive-selector/src/main/java/co/com/bancolombia/{jms => }/sample/selector/app/config/UseCasesConfig.java (88%) rename examples/{mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive => mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector}/domain/exceptions/ParseMessageException.java (68%) rename examples/{mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive => mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector}/domain/model/Request.java (79%) rename examples/mq-reactive-selector/src/main/java/co/com/bancolombia/{jms => }/sample/selector/domain/model/RequestGateway.java (73%) rename examples/{mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive => mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector}/domain/model/Result.java (79%) rename examples/mq-reactive-selector/src/main/java/co/com/bancolombia/{jms => }/sample/selector/domain/usecase/SampleUseCase.java (69%) rename examples/mq-reactive-selector/src/main/java/co/com/bancolombia/{jms => }/sample/selector/drivenadapters/MyMQSender.java (79%) rename examples/mq-reactive-selector/src/main/java/co/com/bancolombia/{jms => }/sample/selector/entrypoints/Rest.java (84%) delete mode 100644 examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/app/config/Config.java delete mode 100644 examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/reqreply/MyRequestReply.java rename examples/{mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive => mq-reactive/src/main/java/co/com/bancolombia/sample}/app/MainApplication.java (67%) create mode 100644 examples/mq-reactive/src/main/java/co/com/bancolombia/sample/app/config/Config.java rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/app/config/UseCasesConfig.java (90%) rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/domain/exceptions/ParseMessageException.java (71%) rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/domain/exceptions/RelatedMessageNotFoundException.java (56%) rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/domain/model/Request.java (82%) rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/domain/model/RequestGateway.java (55%) rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/domain/model/Result.java (82%) rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/domain/model/SenderGateway.java (68%) rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/domain/usecase/SampleReqReplyUseCase.java (51%) rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/domain/usecase/SampleUseCase.java (75%) rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/drivenadapters/MyMQSender.java (63%) create mode 100644 examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/XDomainSender.java create mode 100644 examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReply.java rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/drivenadapters/reqreply/MyRequestReplyAdapter.java (62%) create mode 100644 examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReplyTmp.java rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/entrypoints/MyMQListener.java (85%) rename examples/mq-reactive/src/main/java/co/com/bancolombia/{jms => }/sample/entrypoints/Rest.java (67%) diff --git a/.gitignore b/.gitignore index 595f238..04edbf9 100644 --- a/.gitignore +++ b/.gitignore @@ -289,3 +289,5 @@ gradle-app.setting *.hprof *.log.* FFDC +commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/eda +examples/mq-reactive/src/main/java/co/com/bancolombia/sample/app/config/MQRegistryConfig.java \ No newline at end of file diff --git a/README.md b/README.md index 88638b0..2999dd2 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,9 @@ This library offers a performant setup for JMS Clients. There are some scenarios covered by the library: - Listen messages from a fixed queue. -- Send messages to a fixed queue. -- Listen messages from a temporary queue. -- Send messages to a temporary queue. -- Get messages with specific correlationId from a fixed queue. +- Send messages to a fixed and temporary queues. - Request Reply pattern with automatic temporary queue. +- Request Reply pattern with automatic get message by selector from fixed queue. ## Compatibility @@ -30,6 +28,8 @@ There are some scenarios covered by the library: | 0.6.0 | 2.7.6 | JMS 2 javax | | 1.0.1 | 3.0.6 | JMS 3 jakarta | | 1.1.0 | 3.1.1 | JMS 3 jakarta | +| 1.4.1 | 3.2.1 | JMS 3 jakarta | +| 2.0.0 | 3.2.1 | JMS 3 jakarta | ### Limitations @@ -85,87 +85,12 @@ graph TD The amount of JMSContexts and JMSConsumers is related to the `concurrency` annotation attribute, it is based on JMS 2.0. -#### Listening an autogenerated temporary queue - -To listen a temporary queue you should use the `tempQueueAlias` annotation attribute, the assigned value is the key that -you would be use to get the TemporaryQueue object when needed. - -```java - // For an autogenerated temporary queue -@MQListener(tempQueueAlias = "any-custom-key") -public Mono processFromTemporaryQueue(Message message)throws JMSException{ - String text=((TextMessage)message).getText(); - return doSomething(text); -} -``` - -```java - // For an autogenerated temporary queue non reactive project -@MQListener(tempQueueAlias = "any-custom-key") -public void processFromTemporaryQueue(Message message)throws JMSException{ - String text=((TextMessage)message).getText(); - doSomething(text); -} -``` - -This sample will listen for an autogenerated temporary queue with key `any-custom-key`, the JMS objects structure will -be like this: - -```mermaid -graph TD - X[ConnectionFactory] -->|create| A - A[Connection] -->|create| B(Session) - B --> |create| C(TemporaryQueue) - A -->|create| D(Session) - D -->|create| E(MessageConsumer: TemporaryQueue) - E -->|notifies|F[MessageListener] - A -->|create| G(Session) - G -->|create| H(MessageConsumer: TemporaryQueue) - H -->|notifies|F - A -->|create| I(Session) - I -->|create| J(MessageConsumer: TemporaryQueue) - J -->|notifies|F -``` - The amount of Sessions and MessageConsumers is related to the `concurrency` annotation attribute, it is based on JMS 1.1. -#### Listening for a specific message - -To listen for specific messages is enough with enable message listener selector with the next class annotation: - -```java -@Configuration -@EnableMQSelectorMessageListener -public class AnyConfigurationComponentOrService { -} -``` - -This annotation will create an available bean that offers the ability to get an specific message from a queue using the correlationId attribute, there are two bean options: - -For reactive projects will be `MQMessageSelectorListener` bean which has the next two methods: - -```java -public interface MQMessageSelectorListener { - Mono getMessage(String correlationId); - Mono getMessage(String correlationId, long timeout, Destination destination); -} -``` - -For non-reactive projects will be `MQMessageSelectorListenerSync` bean which has the next two methods: - -```java -public interface MQMessageSelectorListenerSync { - Message getMessage(String correlationId); - Message getMessage(String correlationId, long timeout, Destination destination); -} -``` - -The above beans can throw a `JMSRuntimeException` or a `ReceiveTimeoutException`. - ## Sending messages -To send messages exists the `@EnableMQMessageSender` annotation which enables the producers auto-configuration. +To send messages exists the `@EnableMQGateway` annotation which enables the producers auto-configuration. This configuration creates a JMS objects structure like this: @@ -194,7 +119,7 @@ JMS 2.0. @Component @AllArgsConstructor -@EnableMQMessageSender +@EnableMQGateway(scanBasePackages = "co.com.bancolombia") public class SampleMQMessageSender { private final MQMessageSender sender; // private final MQQueuesContainer container; // Inject it to reference a temporary queue @@ -215,7 +140,7 @@ public class SampleMQMessageSender { @Component @AllArgsConstructor -@EnableMQMessageSender +@EnableMQGateway(scanBasePackages = "co.com.bancolombia") public class SampleMQMessageSender { private final MQMessageSenderSync sender; // private final MQQueuesContainer container; // Inject it to reference a temporary queue @@ -233,6 +158,16 @@ public class SampleMQMessageSender { This sample shows how to send a message to a default destination queue, also shows how reference an autogenerated temporary queue. +If you need to have another message sender, you can define it with the `@MQSender` annotation. +```java +@MQSender(connectionFactory = "domainB") +public interface XDomainSender extends MQMessageSender { +} +``` + +In this case we pass a connectionFactory bean called domainB, this configuration allow you to send messages to another +broker. Remind that a MQMessageSender can send messages to all queues in a QueueManager, so you only need to have one by Queue Manager. + #### Send message to another queue ```java @@ -277,19 +212,14 @@ next interface signatures: ``` For example, you define an interface like the next, so it could be auto implemented by the library: -this [MyRequestReply](examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/reqreply/MyRequestReply.java) -```java -public interface MyRequestReply { - Mono requestReply(String message); -} -``` +this [MyRequestReplyTmp](examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReplyTmp.java) To achieve the auto implementation, you should: - 1. Annotate the application or a configuration bean with @EnableReqReply, optionally you can define the base package + 1. Annotate the application or a configuration bean with @EnableMQGateway, optionally you can define the base package ```java @SpringBootApplication(scanBasePackages = "co.com.bancolombia") - @EnableReqReply(scanBasePackages = "co.com.bancolombia") + @EnableMQGateway(scanBasePackages = "co.com.bancolombia") public class MainApplication { public static void main(String[] args) { SpringApplication.run(MainApplication.class); @@ -299,19 +229,18 @@ To achieve the auto implementation, you should: 2. Annotate the interface with @ReqReply, for example ```java - @ReqReply(requestQueue = "DEV.QUEUE.1", replyQueueTemp = "sample") - public interface MyRequestReply { - Mono requestReply(String message); - } + @ReqReply(requestQueue = "DEV.QUEUE.1") // in queue names you can use ${some.property.name} spring placeholder notation + public interface MyRequestReplyTmp extends MQRequestReply { + } ``` 3. Now you can inject your interface in any spring component. - [MyRequestReplyAdapter](examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/reqreply/MyRequestReplyAdapter.java) + [MyRequestReplyAdapter](examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReplyAdapter.java) ```java @Component @AllArgsConstructor public class MyRequestReplyAdapter implements RequestGateway { - private final MyRequestReply requestReply; + private final MyRequestReplyTmp requestReply; ... } ``` @@ -332,17 +261,11 @@ you can use a Request Reply pattern based on a fixed queue, you should consider In this scenario you should not consider any setup. Following code snippet can show a basic implementation: ```java - public Mono requestReply(String request) { - return sender.send(context -> context.createTextMessage(request)) - .flatMap(listener::getMessage) - .map(this::extractResult); - } - - @SneakyThrows - private String extractResult(Message message) { - return ((TextMessage) message).getText(); + @ReqReply(requestQueue = "DEV.QUEUE.1", replyQueue = "DEV.QUEUE.2", queueType = FIXED) + public interface MyRequestReply extends MQRequestReply { } ``` + Then inject this interface to your adapter like with temporary queue - Multiple Queue Manager or Clustering: In this scenario you should guarantee that: @@ -350,27 +273,8 @@ you can use a Request Reply pattern based on a fixed queue, you should consider - set to `true` the property `commons.jms.input-queue-set-queue-manager` to identify and set the queue manager to the response queue (this guarantees that the application that attends the request send the response to the specific queue manager). + - Then the same like with a single Queue Manager - Following code snippet can show a basic implementation: - - ```java - public Mono requestReply(String request) { - return sender.send(context -> { - Message message = context.createTextMessage(request); - message.setJMSReplyTo(container.get("RESPONSE.QUEUE.NAME")); - return message; - }) - .flatMap(listener::getMessage) - .map(this::extractResult); - } - - @SneakyThrows - private String extractResult(Message message) { - return ((TextMessage) message).getText(); - } - ``` - -In both scenarios you should use the `MQMessageSender`, the `MQMessageSelectorListener` and maybe the `MQQueuesContainer`. ## Setup @@ -387,8 +291,6 @@ the next properties: - **concurrency**: *Number of open connections to listening the queue*, applies for fixed and temporary queues. - **connectionFactory**: *Name of a specific `ConnectionFactory` Bean*, used to create the connections for this consumer. -- **tempQueueAlias**: *An arbitrary key or identifier for an autogenerated temporary queue*, por ejemplo `my-id`, use - only when listen for a temporary queue - **queueCustomizer**: *Name of a specific `MQQueueCustomizer` Bean*, used to customize the listening queue properties before start the consumers. @@ -397,7 +299,6 @@ application.yaml of your application. - `commons.jms.input-concurrency`: Equivalent to `concurrency` annotation property. - `commons.jms.input-queue`: Equivalent to `value` annotation property. -- `commons.jms.input-queue-alias`: Equivalent to `tempQueueAlias` annotation property. - `commons.jms.input-queue-set-queue-manager`: Enable it to set the resolved queue manager when needed. ### Sender properties @@ -424,13 +325,22 @@ This library uses the default bean of kind `ConnectionFactory`, you can customiz To customize sender you should override the default `MQMessageSenderSync` bean refers to [Custom configurations](#Custom-configurations) +#### Multiple Broker + +If you need multi-broker support you only should define the ConnectionFactory bean with a name +and then use this name on each annotation that you need. + +This setting is available for: +- `@MQSender` +- `@MQListener` +- `@ReqReply` + ### Custom configurations You can define custom beans to change default behaviors: - [`MQAutoconfiguration`](commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfiguration.java) -- [`MQAutoconfigurationSender`](commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSender.java) -- [`MQQueueManagerSetter`](commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSelectorListener.java) +- [`MQAutoconfigurationSender`](commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/senders/MQAutoconfigurationSender.java) You should create and register many fixed response queues for request reply, in this case you can override the `MQQueueManagerSetter` as following: @@ -461,6 +371,23 @@ You should create and register many fixed response queues for request reply, in - [`MQUtils`](commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/utils/MQUtils.java) +## Migration + +### From 1.x.x to 2.x.x + +Change notes: +- `@MQListener` has removed support to listen a temporary queue, because `@ReqReply` use this behaviour by default. +- `@ReqReply` has added support to do a request reply pattern using fixed queues with get message by selector. + +Actions: +- `@EnableMQSelectorMessageListener` has been removed, now you can use `@ReqReply` directly using `queueType` attribute + with value `FIXED`. +- `@EnableMQMessageSender` has been removed, now you should use `@EnableMQGateway`. +- `@EnableReqReply` has been removed, now you should use `@EnableMQGateway` passing the same `scanBasePackages` property. +- property `replyQueueTemp` has been renamed to `replyQueue` in `@ReqReply`. +- `commons.jms.input-queue-alias` has been removed now you only can set the alias with `replyQueue`. + + # How can I help? Review the issues, we hear new ideas. Read more [Contributing](./CONTRIBUTING.md) diff --git a/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQDomainMessageSender.java b/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQDomainMessageSender.java new file mode 100644 index 0000000..e9ffb3c --- /dev/null +++ b/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQDomainMessageSender.java @@ -0,0 +1,17 @@ +package co.com.bancolombia.commons.jms.api; + +import jakarta.jms.Destination; +import reactor.core.publisher.Mono; + +public interface MQDomainMessageSender { + Mono send(String domain, Destination destination, MQMessageCreator messageCreator); + + Mono send(String domain, MQMessageCreator messageCreator); + + /** + * You can retrieve the MQMessageSender to avoid queries to Map + * @param domain Domain name or connectionFactory bean name + * @return MQMessageSender + */ + MQMessageSender forDomain(String domain); +} diff --git a/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQMessageSender.java b/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQMessageSender.java index 0f64e14..cd7b43b 100644 --- a/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQMessageSender.java +++ b/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQMessageSender.java @@ -1,8 +1,7 @@ package co.com.bancolombia.commons.jms.api; -import reactor.core.publisher.Mono; - import jakarta.jms.Destination; +import reactor.core.publisher.Mono; public interface MQMessageSender { Mono send(Destination destination, MQMessageCreator messageCreator); diff --git a/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQQueueManagerSetter.java b/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQQueueManagerSetter.java index 1864eda..3224daf 100644 --- a/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQQueueManagerSetter.java +++ b/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQQueueManagerSetter.java @@ -2,6 +2,7 @@ import jakarta.jms.JMSContext; import jakarta.jms.Queue; + import java.util.function.BiConsumer; public interface MQQueueManagerSetter extends BiConsumer { diff --git a/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQRequestReply.java b/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQRequestReply.java index 951d6e6..b062c90 100644 --- a/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQRequestReply.java +++ b/commons-jms-api/src/main/java/co/com/bancolombia/commons/jms/api/MQRequestReply.java @@ -1,8 +1,8 @@ package co.com.bancolombia.commons.jms.api; +import jakarta.jms.Message; import reactor.core.publisher.Mono; -import jakarta.jms.Message; import java.time.Duration; public interface MQRequestReply { diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableReqReply.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableMQGateway.java similarity index 66% rename from commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableReqReply.java rename to commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableMQGateway.java index eb88304..bfa9220 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableReqReply.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableMQGateway.java @@ -1,7 +1,7 @@ package co.com.bancolombia.commons.jms.mq; -import co.com.bancolombia.commons.jms.mq.config.MQAutoconfigurationSender; -import co.com.bancolombia.commons.jms.mq.config.proxy.EnableReqReplyRegistrar; +import co.com.bancolombia.commons.jms.mq.config.MQAnnotationAutoconfiguration; +import co.com.bancolombia.commons.jms.mq.config.senders.MQAutoconfigurationSender; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.AliasFor; @@ -14,9 +14,8 @@ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@Import({MQAutoconfigurationSender.class, EnableReqReplyRegistrar.class}) -public @interface EnableReqReply { - +@Import({MQAutoconfigurationSender.class, MQAnnotationAutoconfiguration.class}) +public @interface EnableMQGateway { @AliasFor("scanBasePackages") String value() default ""; diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableMQMessageSender.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableMQMessageSender.java deleted file mode 100644 index 355cf34..0000000 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableMQMessageSender.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.com.bancolombia.commons.jms.mq; - -import co.com.bancolombia.commons.jms.mq.config.MQAutoconfigurationSender; -import org.springframework.context.annotation.Import; - -import java.lang.annotation.*; - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Import(MQAutoconfigurationSender.class) -public @interface EnableMQMessageSender { -} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableMQSelectorMessageListener.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableMQSelectorMessageListener.java deleted file mode 100644 index 677a236..0000000 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/EnableMQSelectorMessageListener.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.com.bancolombia.commons.jms.mq; - -import co.com.bancolombia.commons.jms.mq.config.MQAutoconfigurationSelectorListener; -import org.springframework.context.annotation.Import; - -import java.lang.annotation.*; - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Import(MQAutoconfigurationSelectorListener.class) -public @interface EnableMQSelectorMessageListener { -} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQListener.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQListener.java index 86054f2..390fd50 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQListener.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQListener.java @@ -1,7 +1,17 @@ package co.com.bancolombia.commons.jms.mq; -import java.lang.annotation.*; +import org.springframework.core.annotation.AliasFor; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation only works for Fixed Queues + */ @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @@ -13,8 +23,16 @@ * * @return Queue Name */ + @AliasFor("listeningQueue") String value() default ""; + /** + * Listening queue name + * @return queue name + */ + @AliasFor("value") + String listeningQueue() default ""; + /** * @return Amount of connections to mq */ @@ -28,14 +46,6 @@ */ String connectionFactory() default ""; - /** - * Alias to register a temporary queue in the MQContainer bean - * - * @return temporary queue alias - * default empty and uses value() for listen a fixed queue - */ - String tempQueueAlias() default ""; - /** * Queue Customizer for listening queue * @@ -49,5 +59,6 @@ * * @return max retries, specify a negative value for infinite retries */ + String maxRetries() default "10"; } diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQListeners.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQListeners.java index e9c124f..1b6ad96 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQListeners.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQListeners.java @@ -1,6 +1,10 @@ package co.com.bancolombia.commons.jms.mq; -import java.lang.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.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQSender.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQSender.java new file mode 100644 index 0000000..170d7b6 --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/MQSender.java @@ -0,0 +1,63 @@ +package co.com.bancolombia.commons.jms.mq; + +import org.springframework.core.annotation.AliasFor; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation only works for Fixed Queues + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface MQSender { + + /** + * Default queue to send + * + * @return Queue Name + */ + @AliasFor("destinationQueue") + String value() default ""; + + @AliasFor("value") + String destinationQueue() default ""; + + /** + * @return Amount of connections to mq + */ + String concurrency() default "0"; + + /** + * Connection Factory for listening context + * + * @return bean name + * default empty and uses available {@link jakarta.jms.ConnectionFactory} bean + */ + String connectionFactory() default ""; + + /** + * Queue Customizer for listening queue + * + * @return bean name + * default empty and uses available {@link co.com.bancolombia.commons.jms.api.MQQueueCustomizer} bean + */ + String queueCustomizer() default ""; + + /** + * Queue Customizer for listening queue + * + * @return bean name + * default empty and uses available {@link co.com.bancolombia.commons.jms.api.MQProducerCustomizer} bean + */ + String producerCustomizer() default ""; + + /** + * Retry config + * + * @return max retries, specify a negative value for infinite retries + */ + String retryConfig() default ""; +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/ReqReply.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/ReqReply.java index 4fc0333..da20f44 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/ReqReply.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/ReqReply.java @@ -1,7 +1,7 @@ package co.com.bancolombia.commons.jms.mq; +import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; import org.springframework.core.annotation.AliasFor; -import org.springframework.stereotype.Service; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -10,16 +10,8 @@ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) -@Service public @interface ReqReply { - - /** - * Queue for request - * - * @return Queue Name - */ - @AliasFor("requestQueue") - String value() default ""; + // Shared /** * @return Amount of connections to mq @@ -34,8 +26,18 @@ */ String connectionFactory() default ""; + // Sender + /** - * Queue for listening + * Queue for request + * + * @return Queue Name + */ + @AliasFor(value = "requestQueue") + String value() default ""; + + /** + * Queue for send request * * @return Queue Name */ @@ -43,25 +45,71 @@ String requestQueue() default ""; /** - * Alias to register a temporary queue in the MQContainer bean + * Queue Customizer for request queue * - * @return temporary queue alias - * default empty and uses value() for listen a fixed queue + * @return bean name + * default empty and uses available {@link co.com.bancolombia.commons.jms.api.MQQueueCustomizer} bean + */ + String queueCustomizer() default ""; + + /** + * Queue Customizer for producer queue + * + * @return bean name + * default empty and uses available {@link co.com.bancolombia.commons.jms.api.MQProducerCustomizer} bean */ - String replyQueueTemp() default ""; + String producerCustomizer() default ""; + + /** + * Retry config + * + * @return max retries, specify a negative value for infinite retries + */ + String retryConfig() default ""; + + // Listener + + /** + * Alias to register a temporary queue in the MQContainer bean when queueType = TEMPORARY + * Fixed queue name when queueType = FIXED + * {@link MQListenerConfig.QueueType} + * + * @return temporary queue alias or queue name + * default empty + */ + String replyQueue() default ""; /** * Queue Customizer for listening queue * * @return bean name - * default empty and uses available MQQueueCustomizer.class bean + * default empty and uses available {@link co.com.bancolombia.commons.jms.api.MQQueueCustomizer} bean */ - String queueCustomizer() default ""; + String replyQueueCustomizer() default ""; /** - * Max message processing retries when error handled + * Listener retries when temporary queues * * @return max retries, specify a negative value for infinite retries */ String maxRetries() default "10"; + + /** + * Type of reply queue: TEMPORARY | FIXED + * {@link MQListenerConfig.QueueType} + * + * @return temporary queue alias + * default empty + */ + MQListenerConfig.QueueType queueType() default MQListenerConfig.QueueType.TEMPORARY; + + /** + * Type of context to retrieve the message + * + * @return selector mode: CONTEXT_SHARED | CONTEXT_PER_MESSAGE + * default CONTEXT_SHARED + */ + MQListenerConfig.SelectorMode selectorMode() default MQListenerConfig.SelectorMode.CONTEXT_SHARED; + + } diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAnnotationAutoconfiguration.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAnnotationAutoconfiguration.java new file mode 100644 index 0000000..72a7677 --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAnnotationAutoconfiguration.java @@ -0,0 +1,44 @@ +package co.com.bancolombia.commons.jms.mq.config; + +import co.com.bancolombia.commons.jms.mq.EnableMQGateway; +import co.com.bancolombia.commons.jms.mq.MQSender; +import co.com.bancolombia.commons.jms.mq.ReqReply; +import co.com.bancolombia.commons.jms.mq.config.utils.MQBeanScanner; +import co.com.bancolombia.commons.jms.mq.config.utils.MQFactoryBean; +import lombok.NonNull; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.util.ClassUtils; + +import java.util.Optional; + +@Log4j2 +public class MQAnnotationAutoconfiguration implements ImportBeanDefinitionRegistrar { + @Override + public void registerBeanDefinitions(@NonNull AnnotationMetadata importingClassMetadata, + @NonNull BeanDefinitionRegistry registry) { + String className = importingClassMetadata.getClassName(); + + importingClassMetadata + .getAnnotations() + .stream(EnableMQGateway.class) + .findFirst() + .ifPresent(annotation -> { + String basePackage = getBasePackage(className, annotation.getValue("value", String.class)); + + new MQBeanScanner(registry, ReqReply.class, MQFactoryBean.class) + .scan(basePackage); + new MQBeanScanner(registry, MQSender.class, MQFactoryBean.class) + .scan(basePackage); + }); + } + + private String getBasePackage(String className, Optional annotation) { + if (annotation.isPresent() && !annotation.get().isEmpty()) { + return annotation.get(); + } + return ClassUtils.getPackageName(className); + } +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfiguration.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfiguration.java index 5e71502..932f9f2 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfiguration.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfiguration.java @@ -1,16 +1,31 @@ package co.com.bancolombia.commons.jms.mq.config; import co.com.bancolombia.commons.jms.api.MQBrokerUtils; +import co.com.bancolombia.commons.jms.api.MQDestinationProvider; +import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; +import co.com.bancolombia.commons.jms.api.MQQueueManagerSetter; import co.com.bancolombia.commons.jms.api.MQQueuesContainer; import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorBuilder; +import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; import co.com.bancolombia.commons.jms.mq.config.health.MQListenerHealthIndicator; +import co.com.bancolombia.commons.jms.mq.listeners.MQExecutorService; import co.com.bancolombia.commons.jms.mq.utils.MQUtils; +import co.com.bancolombia.commons.jms.utils.MQQueueUtils; import co.com.bancolombia.commons.jms.utils.MQQueuesContainerImp; +import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; import com.ibm.mq.jakarta.jms.MQQueue; +import jakarta.jms.Message; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.TimeUnit; import static com.ibm.msg.client.jakarta.wmq.common.CommonConstants.WMQ_MQMD_READ_ENABLED; import static com.ibm.msg.client.jakarta.wmq.common.CommonConstants.WMQ_MQMD_WRITE_ENABLED; @@ -19,7 +34,12 @@ import static com.ibm.msg.client.jakarta.wmq.common.CommonConstants.WMQ_TARGET_CLIENT; @Configuration +@Import(MQAnnotationAutoconfiguration.class) public class MQAutoconfiguration { + public static final String CLASS_LOADER_WARN = "Your class loader has been changed, please add " + + "System.setProperty(\"spring.devtools.restart.enabled\", \"false\"); before SpringApplication.run(...)"; + public static final int MAX_THREADS = 200; + public static final long KEEP_ALIVE_SECONDS = 5L; @Bean @ConditionalOnMissingBean(MQQueueCustomizer.class) @@ -53,7 +73,68 @@ public MQBrokerUtils defaultMqBrokerUtils() { @Bean @ConditionalOnMissingBean(MQHealthListener.class) - public MQHealthListener jmsConnections() { + public MQHealthListener defaultMqHealthListener() { return new MQListenerHealthIndicator(); } + + @Bean + @ConditionalOnMissingBean(RetryableConfig.class) + public RetryableConfig defaultRetryableConfig(MQProperties properties) { + return RetryableConfig.builder() + .maxRetries(properties.getMaxRetries()) + .initialRetryIntervalMillis(properties.getInitialRetryIntervalMillis()) + .multiplier(properties.getRetryMultiplier()) + .build(); + } + + @Bean + @ConditionalOnMissingBean(MQDestinationProvider.class) + public MQDestinationProvider defaultMqDestinationProvider(MQQueueCustomizer customizer, + MQProperties properties) { + return context -> MQQueueUtils.setupFixedQueue(context, MQListenerConfig.builder() + .listeningQueue(properties.getOutputQueue()) + .queueCustomizer(customizer).build()); + } + + @Bean + @ConditionalOnMissingBean(MQProducerCustomizer.class) + public MQProducerCustomizer defaultMQProducerCustomizer(MQProperties properties) { + return producer -> { + if (properties.getProducerTtl() > 0) { + producer.setTimeToLive(properties.getProducerTtl()); + } + }; + } + + @Bean + @ConditionalOnMissingBean(MQQueueManagerSetter.class) + public MQQueueManagerSetter qmSetter(MQProperties properties, MQQueuesContainer container) { + return (jmsContext, queue) -> { + if (properties.isInputQueueSetQueueManager()) { + MQUtils.setQMNameIfNotSet(jmsContext, queue); + } + container.registerQueue(properties.getInputQueue(), queue); + }; + } + + @Bean + @ConditionalOnMissingBean(SelectorBuilder.class) + public SelectorBuilder defaultSelectorBuilder() { + return SelectorBuilder.ofDefaults(); + } + + @Bean + @ConditionalOnMissingBean(MQExecutorService.class) + @ConditionalOnProperty(prefix = "commons.jms", name = "reactive", havingValue = "true") + public MQExecutorService defaultMqExecutorService() { + return new MQExecutorService(0, MAX_THREADS, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, + new SynchronousQueue<>()); + } + + @Bean + @ConditionalOnMissingBean(ReactiveReplyRouter.class) + @ConditionalOnProperty(prefix = "commons.jms", name = "reactive", havingValue = "true") + public ReactiveReplyRouter selectorReactiveReplyRouter() { + return new ReactiveReplyRouter<>(); + } } diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSelectorListener.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSelectorListener.java deleted file mode 100644 index e4fac49..0000000 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSelectorListener.java +++ /dev/null @@ -1,118 +0,0 @@ -package co.com.bancolombia.commons.jms.mq.config; - -import co.com.bancolombia.commons.jms.api.MQMessageSelectorListener; -import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; -import co.com.bancolombia.commons.jms.api.MQQueueManagerSetter; -import co.com.bancolombia.commons.jms.api.MQQueuesContainer; -import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; -import co.com.bancolombia.commons.jms.internal.listener.selector.MQMultiContextMessageSelectorListener; -import co.com.bancolombia.commons.jms.internal.listener.selector.MQMultiContextMessageSelectorListenerSync; -import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.ContextPerMessageStrategy; -import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.ContextSharedStrategy; -import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorModeProvider; -import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; -import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; -import co.com.bancolombia.commons.jms.mq.config.exceptions.MQInvalidListenerException; -import co.com.bancolombia.commons.jms.mq.utils.MQUtils; -import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; -import jakarta.jms.ConnectionFactory; -import jakarta.jms.Message; -import lombok.extern.log4j.Log4j2; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -@Log4j2 -public class MQAutoconfigurationSelectorListener { - public static final int MAX_THREADS = 200; - public static final long KEEP_ALIVE_SECONDS = 5L; - - @Bean - @ConditionalOnMissingBean(ExecutorService.class) - @Qualifier("selectorExecutorService") - @ConditionalOnProperty(prefix = "commons.jms", name = "reactive", havingValue = "true") - public ExecutorService defaultBySelectorExecutorService() { - return new ThreadPoolExecutor(0, MAX_THREADS, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, - new SynchronousQueue<>()); - } - - @Bean - @ConditionalOnMissingBean(SelectorModeProvider.class) - public SelectorModeProvider defaultSelectorModeProvider(@Value("${commons.jms.selector-mode:DEFAULT}") String mode) { - if (MQListenerConfig.SelectorMode.CONTEXT_PER_MESSAGE.name().equals(mode)) { - return (factory, context) -> new ContextPerMessageStrategy(factory); - } - return SelectorModeProvider.defaultSelector(); - } - - @Bean - @ConditionalOnMissingBean(ReactiveReplyRouter.class) - public ReactiveReplyRouter selectorReactiveReplyRouter() { - return new ReactiveReplyRouter<>(); - } - - @Bean - @ConditionalOnMissingBean(MQMessageSelectorListener.class) - @ConditionalOnProperty(prefix = "commons.jms", name = "reactive", havingValue = "true") - public MQMessageSelectorListener defaultMQMessageSelectorListener( - MQMultiContextMessageSelectorListenerSync senderSync, - @Qualifier("selectorExecutorService") ExecutorService bySelectorExecutorService, - ReactiveReplyRouter router) { - return new MQMultiContextMessageSelectorListener(senderSync, bySelectorExecutorService, router); - } - - @Bean - @ConditionalOnMissingBean(MQMultiContextMessageSelectorListenerSync.class) - public MQMultiContextMessageSelectorListenerSync defaultMQMultiContextMessageSelectorListenerSync( - ConnectionFactory cf, @Qualifier("messageSelectorListenerConfig") MQListenerConfig config, - MQHealthListener healthListener, MQProperties properties, SelectorModeProvider selectorModeProvider) { - if (config.getConcurrency() < 1) { - throw new MQInvalidListenerException("Invalid property commons.jms.input-concurrency, minimum value 1, " + - "you have passed " + config.getConcurrency()); - } - if (log.isInfoEnabled()) { - log.info("Creating {} listeners", config.getConcurrency()); - } - RetryableConfig retryableConfig = RetryableConfig.builder() - .maxRetries(properties.getMaxRetries()) - .initialRetryIntervalMillis(properties.getInitialRetryIntervalMillis()) - .multiplier(properties.getRetryMultiplier()) - .build(); - return new MQMultiContextMessageSelectorListenerSync(cf, config, healthListener, retryableConfig, selectorModeProvider); - } - - @Bean - public MQListenerConfig messageSelectorListenerConfig(MQProperties properties, MQQueueCustomizer customizer, - MQQueueManagerSetter setter) { - MQListenerConfig.MQListenerConfigBuilder builder = MQListenerConfig.builder() - .concurrency(properties.getInputConcurrency()) - .queue(properties.getInputQueue()) - .customizer(customizer); - - if (properties.isInputQueueSetQueueManager()) { - builder.qmSetter(setter); - } - - return builder.build(); - } - - @Bean - @ConditionalOnMissingBean(MQQueueManagerSetter.class) - public MQQueueManagerSetter qmSetter(MQProperties properties, MQQueuesContainer container) { - return (jmsContext, queue) -> { - log.info("Self assigning Queue Manager to listening queue: {}", queue.toString()); - if (properties.isInputQueueSetQueueManager()) { - MQUtils.setQMNameIfNotSet(jmsContext, queue); - } - container.registerQueue(properties.getInputQueue(), queue); - }; - } - -} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSender.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSender.java deleted file mode 100644 index e8b2f4f..0000000 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSender.java +++ /dev/null @@ -1,74 +0,0 @@ -package co.com.bancolombia.commons.jms.mq.config; - -import co.com.bancolombia.commons.jms.api.MQDestinationProvider; -import co.com.bancolombia.commons.jms.api.MQMessageSender; -import co.com.bancolombia.commons.jms.api.MQMessageSenderSync; -import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; -import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; -import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; -import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; -import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; -import co.com.bancolombia.commons.jms.internal.sender.MQMultiContextSender; -import co.com.bancolombia.commons.jms.internal.sender.MQMultiContextSenderSync; -import co.com.bancolombia.commons.jms.mq.config.exceptions.MQInvalidSenderException; -import co.com.bancolombia.commons.jms.utils.MQQueueUtils; -import lombok.extern.log4j.Log4j2; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; - -import jakarta.jms.ConnectionFactory; - -@Log4j2 -public class MQAutoconfigurationSender { - - @Bean - @ConditionalOnMissingBean(MQMessageSender.class) - @ConditionalOnProperty(prefix = "commons.jms", name = "reactive", havingValue = "true") - public MQMessageSender defaultMQMessageSender(MQMessageSenderSync senderSync) { - return new MQMultiContextSender(senderSync); - } - - @Bean - @ConditionalOnMissingBean(MQMessageSenderSync.class) - public MQMessageSenderSync defaultMQMessageSenderSync(ConnectionFactory cf, - MQDestinationProvider provider, - MQProducerCustomizer customizer, - MQProperties properties, - MQHealthListener healthListener) { - if (properties.getOutputConcurrency() < 1) { - throw new MQInvalidSenderException("Invalid property commons.jms.output-concurrency, minimum value 1, " + - "you have passed " + properties.getOutputConcurrency()); - } - if (log.isInfoEnabled()) { - log.info("Creating {} senders", properties.getOutputConcurrency()); - } - RetryableConfig retryableConfig = RetryableConfig.builder() - .maxRetries(properties.getMaxRetries()) - .initialRetryIntervalMillis(properties.getInitialRetryIntervalMillis()) - .multiplier(properties.getRetryMultiplier()) - .build(); - return new MQMultiContextSenderSync(cf, properties.getOutputConcurrency(), provider, customizer, healthListener, - retryableConfig); - } - - @Bean - @ConditionalOnMissingBean(MQDestinationProvider.class) - public MQDestinationProvider defaultDestinationProvider(MQQueueCustomizer customizer, - MQProperties properties) { - return context -> MQQueueUtils.setupFixedQueue(context, MQListenerConfig.builder() - .queue(properties.getOutputQueue()) - .customizer(customizer).build()); - } - - @Bean - @ConditionalOnMissingBean(MQProducerCustomizer.class) - public MQProducerCustomizer defaultMQProducerCustomizer(MQProperties properties) { - return producer -> { - if (properties.getProducerTtl() > 0) { - producer.setTimeToLive(properties.getProducerTtl()); - } - }; - } - -} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAnnotationProcessor.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAnnotationProcessor.java deleted file mode 100644 index 4af4e0a..0000000 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAnnotationProcessor.java +++ /dev/null @@ -1,143 +0,0 @@ -package co.com.bancolombia.commons.jms.mq.config; - -import co.com.bancolombia.commons.jms.api.MQBrokerUtils; -import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; -import co.com.bancolombia.commons.jms.api.MQQueuesContainer; -import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; -import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; -import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; -import co.com.bancolombia.commons.jms.mq.MQListener; -import co.com.bancolombia.commons.jms.mq.MQListeners; -import co.com.bancolombia.commons.jms.mq.config.exceptions.MQInvalidListenerException; -import co.com.bancolombia.commons.jms.mq.listeners.MQMessageListener; -import co.com.bancolombia.commons.jms.mq.listeners.MQReactiveMessageListener; -import co.com.bancolombia.commons.jms.utils.MQMessageListenerUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.log4j.Log4j2; -import org.springframework.aop.framework.AopProxyUtils; -import org.springframework.aop.support.AopUtils; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.BeanInitializationException; -import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.beans.factory.config.EmbeddedValueResolver; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.MethodIntrospector; -import org.springframework.core.annotation.AnnotatedElementUtils; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.util.StringUtils; -import org.springframework.util.StringValueResolver; - -import jakarta.jms.ConnectionFactory; -import jakarta.jms.JMSRuntimeException; -import jakarta.jms.MessageListener; - -import java.lang.reflect.Method; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolveConcurrency; -import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolveQueue; -import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolveRetries; - -@Log4j2 -@RequiredArgsConstructor -@Configuration -public class MQListenerAnnotationProcessor implements BeanPostProcessor, BeanFactoryAware { - private final BeanFactory beanFactory; - private StringValueResolver embeddedValueResolver; - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) { - Class targetClass = AopProxyUtils.ultimateTargetClass(bean); - if (AnnotationUtils.isCandidateClass(targetClass, MQListener.class)) { - Map> annotatedMethods = getAnnotatedMethods(targetClass); - processAnnotated(bean, beanName, annotatedMethods); - } - return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); - } - - @Override - public void setBeanFactory(BeanFactory beanFactory) { - if (beanFactory instanceof ConfigurableBeanFactory) { - this.embeddedValueResolver = new EmbeddedValueResolver((ConfigurableBeanFactory) beanFactory); - } - } - - private void processAnnotated(Object bean, String beanName, Map> annotatedMethods) { - if (!annotatedMethods.isEmpty()) { - annotatedMethods.forEach((method, listeners) -> listeners.forEach(listener -> processJmsListener(listener, method, bean))); - if (log.isInfoEnabled()) { - log.info("{} @MQListener methods processed on bean '{}': {}", annotatedMethods.size(), beanName, annotatedMethods); - } - } - } - - private void processJmsListener(MQListener mqListener, Method mostSpecificMethod, Object bean) { - MQProperties properties = resolveBeanWithName("", MQProperties.class); - MQListenerConfig config = validateAnnotationConfig(mqListener, properties); - Method invocableMethod = AopUtils.selectInvocableMethod(mostSpecificMethod, bean.getClass()); - MessageListener processor = getEffectiveMessageListener(bean, invocableMethod, properties.isReactive(), config); - ConnectionFactory cf = resolveBeanWithName(mqListener.connectionFactory(), ConnectionFactory.class); - MQQueuesContainer queuesContainer = beanFactory.getBean(MQQueuesContainer.class); - MQBrokerUtils mqBrokerUtils = beanFactory.getBean(MQBrokerUtils.class); - MQHealthListener exceptionListener = beanFactory.getBean(MQHealthListener.class); - RetryableConfig retryableConfig = RetryableConfig.builder() - .maxRetries(properties.getMaxRetries()) - .initialRetryIntervalMillis(properties.getInitialRetryIntervalMillis()) - .multiplier(properties.getRetryMultiplier()) - .build(); - - try { - MQMessageListenerUtils.createListeners(cf, processor, queuesContainer, mqBrokerUtils, config, - exceptionListener, retryableConfig); - } catch (JMSRuntimeException ex) { - throw new BeanInitializationException("Could not register MQ listener on [" + mostSpecificMethod + "], using ConnectionFactory: " + cf, ex); - } - } - - private MessageListener getEffectiveMessageListener(Object bean, Method invocableMethod, boolean isReactive, MQListenerConfig config) { - return isReactive ? MQReactiveMessageListener.fromBeanAndMethod(bean, invocableMethod, config.getMaxRetries()) : MQMessageListener.fromBeanAndMethod(bean, invocableMethod, config.getMaxRetries()); - } - - private MQListenerConfig validateAnnotationConfig(MQListener config, MQProperties properties) { - // Resolve dynamic values - int concurrency = Integer.parseInt(Objects.requireNonNull(embeddedValueResolver.resolveStringValue(config.concurrency()))); - String queue = embeddedValueResolver.resolveStringValue(config.value()); - MQQueueCustomizer customizer = resolveBeanWithName(config.queueCustomizer(), MQQueueCustomizer.class); - // Map params - if (StringUtils.hasText(queue) && StringUtils.hasText(config.tempQueueAlias())) { - throw new MQInvalidListenerException("Invalid configuration, should define only one of value or " + "tempQueueAlias in @MQListener annotation"); - } - if (StringUtils.hasText(properties.getInputQueue()) && StringUtils.hasText(properties.getInputQueueAlias())) { - throw new MQInvalidListenerException("Invalid configuration, should define only one of " + "commons.jms.input-queue or commons.jms.input-queue-alias in your application.yaml file"); - } - String temporaryQueue = resolveQueue(config.tempQueueAlias(), queue, properties.getInputQueueAlias()); - String fixedQueue = resolveQueue(queue, temporaryQueue, properties.getInputQueue()); - int finalConcurrency = resolveConcurrency(concurrency, properties.getInputConcurrency()); - int maxRetries = resolveRetries(config.maxRetries()); - MQListenerConfig listenerConfig = MQListenerConfig.builder().concurrency(finalConcurrency).tempQueueAlias(temporaryQueue).queue(fixedQueue).connectionFactory(config.connectionFactory()).customizer(customizer).maxRetries(maxRetries).build(); - if (!StringUtils.hasText(listenerConfig.getQueue()) && !StringUtils.hasText(listenerConfig.getTempQueueAlias())) { - throw new MQInvalidListenerException("Invalid configuration, should define one of value or tempQueueAlias"); - } - return listenerConfig; - } - - private Map> getAnnotatedMethods(Class targetClass) { - return MethodIntrospector.selectMethods(targetClass, (MethodIntrospector.MetadataLookup>) method -> { - Set listenerMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(method, MQListener.class, MQListeners.class); - return (!listenerMethods.isEmpty() ? listenerMethods : null); - }); - } - - private T resolveBeanWithName(String beanName, Class tClass) { - if (StringUtils.hasText(beanName)) { - return beanFactory.getBean(beanName, tClass); - } else { - return beanFactory.getBean(tClass); - } - } - -} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAutoconfiguration.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAutoconfiguration.java new file mode 100644 index 0000000..b60fdd5 --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAutoconfiguration.java @@ -0,0 +1,18 @@ +package co.com.bancolombia.commons.jms.mq.config; + +import co.com.bancolombia.commons.jms.mq.config.factory.MQListenerFactory; +import lombok.AllArgsConstructor; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.annotation.Configuration; +import org.springframework.lang.NonNull; + +@Configuration +@AllArgsConstructor +public class MQListenerAutoconfiguration implements BeanPostProcessor { + private final MQSpringResolver resolver; + @Override + public Object postProcessAfterInitialization(@NonNull Object bean, @NonNull String beanName) { + MQListenerFactory.postProcessAfterInitialization(resolver, bean, beanName); + return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); + } +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQProperties.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQProperties.java index 1bba68a..5b447e7 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQProperties.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQProperties.java @@ -1,26 +1,45 @@ package co.com.bancolombia.commons.jms.mq.config; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Data @Component @ConfigurationProperties(prefix = "commons.jms") +@NoArgsConstructor +@AllArgsConstructor +@Builder public class MQProperties { + @Builder.Default + public static final String DEFAULT_DOMAIN = "app"; + @Builder.Default public static final int DEFAULT_CONCURRENCY = 1; + @Builder.Default public static final int DEFAULT_MAX_RETRIES = 10; + @Builder.Default public static final int DEFAULT_INITIAL_RETRY_INTERVAL_MILLIS = 1000; + @Builder.Default public static final double DEFAULT_RETRY_MULTIPLIER = 1.5; + @Builder.Default private int outputConcurrency = DEFAULT_CONCURRENCY; - private String outputQueue; + @Builder.Default private int inputConcurrency = DEFAULT_CONCURRENCY; - private String inputQueue; - private String inputQueueAlias; + @Builder.Default private boolean inputQueueSetQueueManager = false; + @Builder.Default private long producerTtl = 0; + @Builder.Default private boolean reactive = false; + @Builder.Default private int maxRetries = DEFAULT_MAX_RETRIES; + @Builder.Default private int initialRetryIntervalMillis = DEFAULT_INITIAL_RETRY_INTERVAL_MILLIS; + @Builder.Default private double retryMultiplier = DEFAULT_RETRY_MULTIPLIER; + private String outputQueue; + private String inputQueue; } diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQSpringResolver.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQSpringResolver.java new file mode 100644 index 0000000..0b46bac --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/MQSpringResolver.java @@ -0,0 +1,105 @@ +package co.com.bancolombia.commons.jms.mq.config; + +import co.com.bancolombia.commons.jms.api.MQBrokerUtils; +import co.com.bancolombia.commons.jms.api.MQQueueManagerSetter; +import co.com.bancolombia.commons.jms.api.MQQueuesContainer; +import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorBuilder; +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; +import co.com.bancolombia.commons.jms.mq.config.senders.MQSenderContainer; +import co.com.bancolombia.commons.jms.mq.listeners.MQExecutorService; +import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; +import jakarta.jms.ConnectionFactory; +import jakarta.jms.Message; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.context.EmbeddedValueResolverAware; +import org.springframework.core.ResolvableType; +import org.springframework.core.annotation.MergedAnnotation; +import org.springframework.lang.NonNull; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.util.StringValueResolver; + +@Component +@RequiredArgsConstructor +public class MQSpringResolver implements EmbeddedValueResolverAware { + private final BeanFactory beanFactory; + private StringValueResolver resolver; + + public T resolveBean(String name, Class clazz) { + if (StringUtils.hasText(name)) { + return beanFactory.getBean(name, clazz); + } else { + return resolveBean(clazz); + } + } + + public T resolveBean(Class clazz) { + return beanFactory.getBean(clazz); + } + + public ObjectProvider getProvider(ResolvableType type) { + return beanFactory.getBeanProvider(type); + } + + public StringValueResolver getResolver() { + return resolver; + } + + public ConnectionFactory getConnectionFactory(String name) { + return resolveBean(name, ConnectionFactory.class); + } + + public MQQueuesContainer getQueuesContainer() { + return beanFactory.getBean(MQQueuesContainer.class); + } + + public MQProperties getProperties() { + return beanFactory.getBean(MQProperties.class); + } + + public MQBrokerUtils getBrokerUtils() { + return beanFactory.getBean(MQBrokerUtils.class); + } + + public MQHealthListener getHealthListener() { + return beanFactory.getBean(MQHealthListener.class); + } + + public RetryableConfig getRetryableConfig() { + return beanFactory.getBean(RetryableConfig.class); + } + + public MQExecutorService getMqExecutorService() { + return beanFactory.getBean(MQExecutorService.class); + } + + public MQQueueManagerSetter getMqQueueManagerSetter() { + return beanFactory.getBean(MQQueueManagerSetter.class); + } + + public MQSenderContainer getMqSenderContainer() { + return beanFactory.getBean(MQSenderContainer.class); + } + + public SelectorBuilder getSelectorBuilder() { + return beanFactory.getBean(SelectorBuilder.class); + } + + public String resolveString(String value) { + return getResolver().resolveStringValue(value); + } + + @SuppressWarnings("unchecked") + public ReactiveReplyRouter resolveReplier() { + ResolvableType resolvable = ResolvableType.forClassWithGenerics(ReactiveReplyRouter.class, Message.class); + return (ReactiveReplyRouter) getProvider(resolvable).getIfAvailable(ReactiveReplyRouter::new); + } + + @Override + public void setEmbeddedValueResolver(@NonNull StringValueResolver resolver) { + this.resolver = resolver; + } +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQListenerFactory.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQListenerFactory.java new file mode 100644 index 0000000..e29d940 --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQListenerFactory.java @@ -0,0 +1,138 @@ +package co.com.bancolombia.commons.jms.mq.config.factory; + +import co.com.bancolombia.commons.jms.api.MQBrokerUtils; +import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; +import co.com.bancolombia.commons.jms.api.MQQueuesContainer; +import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; +import co.com.bancolombia.commons.jms.mq.MQListener; +import co.com.bancolombia.commons.jms.mq.MQListeners; +import co.com.bancolombia.commons.jms.mq.config.MQProperties; +import co.com.bancolombia.commons.jms.mq.config.MQSpringResolver; +import co.com.bancolombia.commons.jms.mq.config.exceptions.MQInvalidListenerException; +import co.com.bancolombia.commons.jms.mq.listeners.MQMessageListener; +import co.com.bancolombia.commons.jms.mq.listeners.MQReactiveMessageListener; +import co.com.bancolombia.commons.jms.utils.MQMessageListenerUtils; +import jakarta.jms.ConnectionFactory; +import jakarta.jms.JMSRuntimeException; +import jakarta.jms.MessageListener; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.springframework.aop.framework.AopProxyUtils; +import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.BeanInitializationException; +import org.springframework.core.MethodIntrospector; +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.lang.NonNull; +import org.springframework.util.StringUtils; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolve; +import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolveConcurrency; +import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolveRetries; + +@Log4j2 +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class MQListenerFactory { + + public static void postProcessAfterInitialization(MQSpringResolver resolver, + @NonNull Object bean, + @NonNull String beanName) { + Class targetClass = AopProxyUtils.ultimateTargetClass(bean); + if (AnnotationUtils.isCandidateClass(targetClass, MQListener.class)) { + Map> annotatedMethods = getAnnotatedMethods(targetClass); + processAnnotated(bean, beanName, annotatedMethods, resolver); + } + } + + private static Map> getAnnotatedMethods(Class targetClass) { + return MethodIntrospector.selectMethods(targetClass, + (MethodIntrospector.MetadataLookup>) method -> { + Set listenerMethods = + AnnotatedElementUtils.getMergedRepeatableAnnotations(method, MQListener.class, + MQListeners.class); + return (!listenerMethods.isEmpty() ? listenerMethods : null); + }); + } + + private static void processAnnotated(Object bean, String beanName, Map> annotatedMethods, + MQSpringResolver resolver) { + if (!annotatedMethods.isEmpty()) { + annotatedMethods.forEach((method, annotations) -> + annotations.forEach(annotation -> processJmsListener(annotation, method, bean, resolver))); + if (log.isInfoEnabled()) { + log.info("{} @MQListener methods processed on bean '{}': {}", + annotatedMethods.size(), beanName, annotatedMethods); + } + } + } + + // Build listeners + + private static void processJmsListener(MQListener annotation, Method mostSpecificMethod, Object bean, + MQSpringResolver resolver) { + MQQueuesContainer queuesContainer = resolver.getQueuesContainer(); + MQBrokerUtils brokerUtils = resolver.getBrokerUtils(); + MQHealthListener healthListener = resolver.getHealthListener(); + RetryableConfig retryableConfig = resolver.getRetryableConfig(); + + MQProperties properties = resolver.getProperties(); + MQListenerConfig listenerConfig = buildConfig(annotation, mostSpecificMethod, properties, resolver, bean); + + try { + MQMessageListenerUtils.createListeners( + listenerConfig, + queuesContainer, + brokerUtils, + healthListener, + retryableConfig); + } catch (JMSRuntimeException ex) { + throw new BeanInitializationException("Could not register MQ listener on [" + mostSpecificMethod + + "], using ConnectionFactory: " + listenerConfig.getConnectionFactory(), ex); + } + } + + private static MQListenerConfig buildConfig(MQListener annotation, Method mostSpecificMethod, + MQProperties properties, MQSpringResolver resolver, Object bean) { + // Resolve dynamic values + String queueName = resolve(resolver.resolveString(annotation.value()), properties.getInputQueue()); + MQQueueCustomizer customizer = resolver.resolveBean(annotation.queueCustomizer(), MQQueueCustomizer.class); + + int concurrency = Integer.parseInt(Objects.requireNonNull(resolver.resolveString(annotation.concurrency()))); + int finalConcurrency = resolveConcurrency(concurrency, properties.getInputConcurrency()); + int maxRetries = resolveRetries(annotation.maxRetries()); + ConnectionFactory connectionFactory = resolver.getConnectionFactory(annotation.connectionFactory()); + + Method invocableMethod = AopUtils.selectInvocableMethod(mostSpecificMethod, bean.getClass()); + MessageListener processor = buildMessageListener(bean, invocableMethod, properties.isReactive(), finalConcurrency); + + MQListenerConfig listenerConfig = MQListenerConfig.builder() + .connectionFactory(connectionFactory) + .queueCustomizer(customizer) + .messageListener(processor) + .listeningQueue(queueName) + .maxRetries(maxRetries) + .concurrency(finalConcurrency) + .build(); + if (!StringUtils.hasText(listenerConfig.getListeningQueue())) { + throw new MQInvalidListenerException( + "Invalid configuration, should define one of value or commons.jms.input-queue"); + } + return listenerConfig; + } + + private static MessageListener buildMessageListener(Object bean, Method invocableMethod, boolean isReactive, + int maxRetries) { + return isReactive ? + MQReactiveMessageListener.fromBeanAndMethod(bean, invocableMethod, maxRetries) + : MQMessageListener.fromBeanAndMethod(bean, invocableMethod, maxRetries); + } + +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQReqReplyFactory.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQReqReplyFactory.java new file mode 100644 index 0000000..0973084 --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQReqReplyFactory.java @@ -0,0 +1,178 @@ +package co.com.bancolombia.commons.jms.mq.config.factory; + + +import co.com.bancolombia.commons.jms.api.MQBrokerUtils; +import co.com.bancolombia.commons.jms.api.MQMessageSelectorListener; +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.api.MQMessageSenderSync; +import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; +import co.com.bancolombia.commons.jms.api.MQQueuesContainer; +import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import co.com.bancolombia.commons.jms.internal.listener.selector.MQMultiContextMessageSelectorListener; +import co.com.bancolombia.commons.jms.internal.listener.selector.MQMultiContextMessageSelectorListenerSync; +import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.ContextPerMessageStrategy; +import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorBuilder; +import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorModeProvider; +import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; +import co.com.bancolombia.commons.jms.mq.ReqReply; +import co.com.bancolombia.commons.jms.mq.config.MQProperties; +import co.com.bancolombia.commons.jms.mq.config.MQSpringResolver; +import co.com.bancolombia.commons.jms.mq.config.exceptions.MQInvalidListenerException; +import co.com.bancolombia.commons.jms.mq.listeners.MQExecutorService; +import co.com.bancolombia.commons.jms.mq.listeners.MQRequestReplyListener; +import co.com.bancolombia.commons.jms.mq.listeners.MQRequestReplySelector; +import co.com.bancolombia.commons.jms.utils.MQMessageListenerUtils; +import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; +import com.ibm.mq.jakarta.jms.MQQueue; +import jakarta.jms.ConnectionFactory; +import jakarta.jms.Destination; +import jakarta.jms.JMSRuntimeException; +import jakarta.jms.Message; +import jakarta.jms.Queue; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.BeanInitializationException; +import org.springframework.util.StringUtils; + +import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolve; +import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolveConcurrency; +import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolveRetries; + +@Log4j2 +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class MQReqReplyFactory { + + public static Object createMQReqReply(ReqReply annotation, MQSpringResolver resolver, String beanName) { + log.info("Creating bean instance for {} class", beanName); + MQProperties properties = resolver.getProperties(); + if (properties.isReactive()) { + resolver.resolveBean(MQMessageSender.class); + } else { + resolver.resolveBean(MQMessageSenderSync.class); + } + MQListenerConfig listenerConfig = validateAnnotationConfig(annotation, resolver, properties, beanName); + MQMessageSender sender = (MQMessageSender) MQSenderFactory.fromReqReply(annotation, resolver, beanName); + MQBrokerUtils mqBrokerUtils = resolver.getBrokerUtils(); + MQHealthListener healthListener = resolver.getHealthListener(); + MQQueuesContainer queuesContainer = resolver.getQueuesContainer(); + RetryableConfig retryableConfig = resolver.getRetryableConfig(); + Destination destination = resolveDestination(annotation, resolver, properties); + if (listenerConfig.getQueueType() == MQListenerConfig.QueueType.FIXED) { + SelectorModeProvider selectorModeProvider = getSelectorModeProvider(annotation.selectorMode()); + MQMultiContextMessageSelectorListenerSync selectorListener = new MQMultiContextMessageSelectorListenerSync( + listenerConfig, + healthListener, + retryableConfig, + selectorModeProvider, + queuesContainer); + if (properties.isReactive()) { + ReactiveReplyRouter router = resolver.resolveReplier(); + MQExecutorService executorService = resolver.getMqExecutorService(); + SelectorBuilder selector = resolver.getSelectorBuilder(); + MQMessageSelectorListener reactiveSelectorListener = new MQMultiContextMessageSelectorListener( + selectorListener, + executorService, + router); + return new MQRequestReplySelector( + sender, + queuesContainer, + destination, + listenerConfig.getListeningQueue(), + selector, + reactiveSelectorListener); + } else { + throw new RuntimeException("Not available for non reactive projects"); // TODO: Make it available + } + } else { + if (properties.isReactive()) { + ReactiveReplyRouter router = resolver.resolveReplier(); + MQRequestReplyListener senderWithRouter = new MQRequestReplyListener( + sender, + router, + queuesContainer, + destination, + listenerConfig.getListeningQueue(), + listenerConfig.getMaxRetries()); + try { + MQListenerConfig finalListenerConfig = listenerConfig.toBuilder() + .messageListener(senderWithRouter) + .build(); + MQMessageListenerUtils.createListeners( + finalListenerConfig, + queuesContainer, + mqBrokerUtils, + healthListener, + retryableConfig); + } catch (JMSRuntimeException ex) { + throw new BeanInitializationException("Could not create @ReqReply bean named " + beanName + + " with connectionFactory: " + listenerConfig.getConnectionFactory(), ex); + } + return senderWithRouter; + } else { + throw new RuntimeException("Not available for non reactive projects"); // TODO: Make it available + } + } + } + + @SneakyThrows + private static Destination resolveDestination(ReqReply annotation, MQSpringResolver resolver, + MQProperties properties) { + String requestQueue = resolver.resolveString(annotation.requestQueue()); + String queueCustomizerName = resolver.resolveString(annotation.queueCustomizer()); + String name = StringUtils.hasText(requestQueue) ? requestQueue : properties.getOutputQueue(); + MQQueueCustomizer customizer = resolver.resolveBean(queueCustomizerName, MQQueueCustomizer.class); + Queue queue = new MQQueue(name); + customizer.customize(queue); + return queue; + } + + private static MQListenerConfig validateAnnotationConfig(ReqReply annotation, MQSpringResolver resolver, + MQProperties properties, String className) { + // Annotation property + String concurrencyStr = resolver.resolveString(annotation.concurrency()); + String maxRetriesStr = resolver.resolveString(annotation.maxRetries()); + String replyQueue = resolver.resolveString(annotation.replyQueue()); + String queueCustomizerName = annotation.queueCustomizer(); + MQListenerConfig.QueueType queueType = annotation.queueType(); + MQListenerConfig.SelectorMode selectorMode = annotation.selectorMode(); + + // Resolve dynamic values + int finalConcurrency = resolveConcurrency(Integer.parseInt(concurrencyStr), properties.getInputConcurrency()); + int maxRetries = resolveRetries(maxRetriesStr); + MQQueueCustomizer customizer = resolver.resolveBean(queueCustomizerName, MQQueueCustomizer.class); + if (queueType == MQListenerConfig.QueueType.TEMPORARY) { + replyQueue = resolve(replyQueue, className); + } else { + replyQueue = resolve(replyQueue, properties.getInputQueue()); + } + ConnectionFactory connectionFactory = resolver.getConnectionFactory(annotation.connectionFactory()); + MQListenerConfig.MQListenerConfigBuilder builder = MQListenerConfig.builder() + .connectionFactory(connectionFactory) + .concurrency(finalConcurrency) + .queueType(queueType) + .selectorMode(selectorMode) + .listeningQueue(replyQueue) + .queueCustomizer(customizer) + .maxRetries(maxRetries); + if (properties.isInputQueueSetQueueManager()) { + builder.qmSetter(resolver.getMqQueueManagerSetter()); + } + MQListenerConfig listenerConfig = builder.build(); + if (!StringUtils.hasText(listenerConfig.getListeningQueue())) { + throw new MQInvalidListenerException("Invalid configuration, should define replyQueue and queueType"); + } + return listenerConfig; + } + + // Selector + private static SelectorModeProvider getSelectorModeProvider(MQListenerConfig.SelectorMode mode) { + if (MQListenerConfig.SelectorMode.CONTEXT_PER_MESSAGE == mode) { + return (factory, context) -> new ContextPerMessageStrategy(factory); + } + return SelectorModeProvider.defaultSelector(); + } +} + diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQSenderFactory.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQSenderFactory.java new file mode 100644 index 0000000..b5ac6cf --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/MQSenderFactory.java @@ -0,0 +1,95 @@ +package co.com.bancolombia.commons.jms.mq.config.factory; + +import co.com.bancolombia.commons.jms.api.MQDestinationProvider; +import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; +import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; +import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; +import co.com.bancolombia.commons.jms.internal.models.MQSenderConfig; +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; +import co.com.bancolombia.commons.jms.internal.sender.MQMultiContextSender; +import co.com.bancolombia.commons.jms.internal.sender.MQMultiContextSenderSync; +import co.com.bancolombia.commons.jms.mq.MQSender; +import co.com.bancolombia.commons.jms.mq.ReqReply; +import co.com.bancolombia.commons.jms.mq.config.MQProperties; +import co.com.bancolombia.commons.jms.mq.config.senders.MQSenderContainer; +import co.com.bancolombia.commons.jms.mq.config.MQSpringResolver; +import co.com.bancolombia.commons.jms.mq.config.factory.model.AnnotationSenderSettings; +import co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils; +import co.com.bancolombia.commons.jms.utils.MQQueueUtils; +import jakarta.jms.ConnectionFactory; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.log4j.Log4j2; + +import static co.com.bancolombia.commons.jms.mq.config.MQProperties.DEFAULT_DOMAIN; +import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolve; +import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolveConcurrency; +import static java.util.Objects.requireNonNull; + +@Log4j2 +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class MQSenderFactory { + + public static Object fromMQSender(MQSender annotation, MQSpringResolver resolver, String beanName) { + AnnotationSenderSettings settings = AnnotationSenderSettings.from(annotation); + return fromAnnotationSettings(settings, resolver, beanName); + } + + public static Object fromReqReply(ReqReply annotation, MQSpringResolver resolver, String beanName) { + AnnotationSenderSettings settings = AnnotationSenderSettings.from(annotation); + return fromAnnotationSettings(settings, resolver, beanName); + } + + private static Object fromAnnotationSettings(AnnotationSenderSettings settings, MQSpringResolver resolver, + String beanName) { + log.info("Creating bean instance for {} class", beanName); + String domain = AnnotationUtils.resolve(settings.getConnectionFactory(), DEFAULT_DOMAIN); + MQSenderContainer container = resolver.getMqSenderContainer(); + MQProperties properties = resolver.getProperties(); + if (container.containsKey(domain)) { + log.info("Using already created bean instance for {} class", beanName); + return properties.isReactive() ? container.getReactive(domain) : container.getImperative(domain); + } + + ConnectionFactory connectionFactory = resolver.getConnectionFactory(settings.getConnectionFactory()); + int concurrency = Integer.parseInt(requireNonNull(resolver.resolveString(settings.getConcurrency()))); + int finalConcurrency = resolveConcurrency(concurrency, properties.getOutputConcurrency()); + String realQueue = resolve(resolver.resolveString(settings.getDestinationQueue()), properties.getOutputQueue()); + MQProducerCustomizer pCust = resolver.resolveBean(settings.getProducerCustomizer(), MQProducerCustomizer.class); + MQQueueCustomizer queueCust = resolver.resolveBean(settings.getQueueCustomizer(), MQQueueCustomizer.class); + RetryableConfig retryableConfig = resolver.resolveBean(settings.getRetryConfig(), RetryableConfig.class); + MQDestinationProvider destinationProvider = buildMqDestinationProvider(queueCust, realQueue); + MQHealthListener healthListener = resolver.getHealthListener(); + + MQSenderConfig config = MQSenderConfig.builder() + .connectionFactory(connectionFactory) + .concurrency(finalConcurrency) + .destinationProvider(destinationProvider) + .producerCustomizer(pCust) + .healthListener(healthListener) + .retryableConfig(retryableConfig) + .build(); + + return fromSenderConfig(domain, container, properties, config); + } + + public static Object fromSenderConfig(String domain, MQSenderContainer container, + MQProperties properties, MQSenderConfig config) { + MQMultiContextSenderSync sender = new MQMultiContextSenderSync(config); + if (properties.isReactive()) { + MQMultiContextSender senderReactive = new MQMultiContextSender(sender); + container.put(domain, senderReactive); + return senderReactive; + } else { + container.put(domain, sender); + return sender; + } + } + + private static MQDestinationProvider buildMqDestinationProvider(MQQueueCustomizer customizer, String queueName) { + return context -> MQQueueUtils.setupFixedQueue(context, MQListenerConfig.builder() + .listeningQueue(queueName) + .queueCustomizer(customizer).build()); + } +} \ No newline at end of file diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/model/AnnotationSenderSettings.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/model/AnnotationSenderSettings.java new file mode 100644 index 0000000..e320f79 --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/factory/model/AnnotationSenderSettings.java @@ -0,0 +1,43 @@ +package co.com.bancolombia.commons.jms.mq.config.factory.model; + + +import co.com.bancolombia.commons.jms.mq.MQSender; +import co.com.bancolombia.commons.jms.mq.ReqReply; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class AnnotationSenderSettings { + private final String concurrency; + private final String destinationQueue; + private final String connectionFactory; + private final String queueCustomizer; + private final String producerCustomizer; + private final String retryConfig; + + public static AnnotationSenderSettings from(MQSender annotation) { + return AnnotationSenderSettings.builder() + .concurrency(annotation.concurrency()) + .destinationQueue(annotation.destinationQueue()) + .connectionFactory(annotation.connectionFactory()) + .queueCustomizer(annotation.queueCustomizer()) + .producerCustomizer(annotation.producerCustomizer()) + .retryConfig(annotation.retryConfig()) + .build(); + } + + public static AnnotationSenderSettings from(ReqReply annotation) { + return AnnotationSenderSettings.builder() + .concurrency(annotation.concurrency()) + .destinationQueue(annotation.requestQueue()) + .connectionFactory(annotation.connectionFactory()) + .queueCustomizer(annotation.queueCustomizer()) + .producerCustomizer(annotation.producerCustomizer()) + .retryConfig(annotation.retryConfig()) + .build(); + } +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/health/MQListenerHealthIndicator.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/health/MQListenerHealthIndicator.java index 9ea785b..53733b7 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/health/MQListenerHealthIndicator.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/health/MQListenerHealthIndicator.java @@ -1,12 +1,12 @@ package co.com.bancolombia.commons.jms.mq.config.health; import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import jakarta.jms.JMSException; import lombok.extern.log4j.Log4j2; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.Status; -import jakarta.jms.JMSException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/proxy/EnableReqReplyRegistrar.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/proxy/EnableReqReplyRegistrar.java deleted file mode 100644 index d21e1aa..0000000 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/proxy/EnableReqReplyRegistrar.java +++ /dev/null @@ -1,37 +0,0 @@ -package co.com.bancolombia.commons.jms.mq.config.proxy; - -import co.com.bancolombia.commons.jms.mq.EnableReqReply; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.util.ClassUtils; - -import java.lang.annotation.Annotation; -import java.util.Optional; - -public class EnableReqReplyRegistrar implements ImportBeanDefinitionRegistrar { - - @Override - public void registerBeanDefinitions(AnnotationMetadata configMetadata, BeanDefinitionRegistry registry) { - String className = configMetadata.getClassName(); - - configMetadata - .getAnnotations() - .stream(getAnnotationType()) - .forEach(annotation -> { - String basePackage = getBasePackage(className, annotation.getValue("value", String.class)); - new ReqReplyBeanScanner(registry).scan(basePackage); - }); - } - - protected Class getAnnotationType() { - return EnableReqReply.class; - } - - private String getBasePackage(String className, Optional annotation) { - if (annotation.isPresent() && !annotation.get().isEmpty()) { - return annotation.get(); - } - return ClassUtils.getPackageName(className); - } -} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/proxy/InterfaceComponentProxyFactoryBean.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/proxy/InterfaceComponentProxyFactoryBean.java deleted file mode 100644 index 1b79555..0000000 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/proxy/InterfaceComponentProxyFactoryBean.java +++ /dev/null @@ -1,209 +0,0 @@ -package co.com.bancolombia.commons.jms.mq.config.proxy; - - -import co.com.bancolombia.commons.jms.api.MQBrokerUtils; -import co.com.bancolombia.commons.jms.api.MQMessageSender; -import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; -import co.com.bancolombia.commons.jms.api.MQQueuesContainer; -import co.com.bancolombia.commons.jms.api.MQRequestReply; -import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; -import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; -import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; -import co.com.bancolombia.commons.jms.mq.ReqReply; -import co.com.bancolombia.commons.jms.mq.config.MQProperties; -import co.com.bancolombia.commons.jms.mq.config.exceptions.MQInvalidListenerException; -import co.com.bancolombia.commons.jms.mq.listeners.MQRequestReplyListener; -import co.com.bancolombia.commons.jms.utils.MQMessageListenerUtils; -import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; -import com.ibm.mq.jakarta.jms.MQQueue; -import jakarta.jms.Queue; -import lombok.SneakyThrows; -import lombok.extern.log4j.Log4j2; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.BeanInitializationException; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; -import org.springframework.beans.factory.config.EmbeddedValueResolver; -import org.springframework.cglib.proxy.InvocationHandler; -import org.springframework.cglib.proxy.Proxy; -import org.springframework.core.ResolvableType; -import org.springframework.core.annotation.MergedAnnotation; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.util.ClassUtils; -import org.springframework.util.StringUtils; - -import jakarta.jms.ConnectionFactory; -import jakarta.jms.Destination; -import jakarta.jms.JMSRuntimeException; -import jakarta.jms.Message; -import java.lang.reflect.Method; -import java.util.Arrays; - -import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolveConcurrency; -import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolveQueue; -import static co.com.bancolombia.commons.jms.mq.config.utils.AnnotationUtils.resolveRetries; -import static org.springframework.util.ClassUtils.resolveClassName; - -@Log4j2 -public class InterfaceComponentProxyFactoryBean implements FactoryBean, BeanFactoryAware { - private final AnnotationMetadata metadata; - private final Class objectType; - private BeanFactory beanFactory; - private EmbeddedValueResolver embeddedValueResolver; - - public InterfaceComponentProxyFactoryBean(AnnotationMetadata metadata) { - this.metadata = metadata; - objectType = resolveClassName(metadata.getClassName(), null); - } - - @Override - public void setBeanFactory(BeanFactory beanFactory) { - this.beanFactory = beanFactory; - if (beanFactory instanceof ConfigurableBeanFactory) { - this.embeddedValueResolver = new EmbeddedValueResolver((ConfigurableBeanFactory) beanFactory); - } - } - - @Override - public Object getObject() { - log.info("Creating req reply bean for {}", getObjectType()); - if (getObjectType() != null && !InterfaceComponentProxyFactoryBean.class.getClassLoader().equals(getObjectType().getClassLoader())) { - log.warn("Your class loader has been changed, please add System.setProperty(\"spring.devtools.restart.enabled\", \"false\"); before SpringApplication.run(...)"); - } - return Proxy.newProxyInstance(InterfaceComponentProxyFactoryBean.class.getClassLoader(), - new Class[]{getObjectType()}, - new Target(getObjectType(), buildInstance())); - } - - private MQRequestReply buildInstance() { - MQMessageSender sender = beanFactory.getBean(MQMessageSender.class); - ReactiveReplyRouter router = resolveReplier(); - MQQueuesContainer container = beanFactory.getBean(MQQueuesContainer.class); - String className = ClassUtils.getShortName(metadata.getClassName()); - MQProperties properties = resolveBeanWithName("", MQProperties.class); - MergedAnnotation annotation = metadata.getAnnotations().get(ReqReply.class); - MQListenerConfig config = validateAnnotationConfig(annotation, properties, className); - ConnectionFactory cf = resolveBeanWithName(config.getConnectionFactory(), ConnectionFactory.class); - MQBrokerUtils mqBrokerUtils = beanFactory.getBean(MQBrokerUtils.class); - MQHealthListener healthListener = beanFactory.getBean(MQHealthListener.class); - - Destination destination = resolveDestination(annotation, properties); - - MQRequestReplyListener senderWithRouter = new MQRequestReplyListener(sender, router, container, destination, - config.getTempQueueAlias(), config.getMaxRetries()); - - RetryableConfig retryableConfig = RetryableConfig.builder() - .maxRetries(properties.getMaxRetries()) - .initialRetryIntervalMillis(properties.getInitialRetryIntervalMillis()) - .multiplier(properties.getRetryMultiplier()) - .build(); - try { - MQMessageListenerUtils.createListeners(cf, senderWithRouter, container, mqBrokerUtils, config, healthListener, - retryableConfig); - } catch (JMSRuntimeException ex) { - throw new BeanInitializationException("Could not create request reply defined in " + className - + " connectionFactory: " + cf, ex); - } - - return senderWithRouter; - } - - @SneakyThrows - private Destination resolveDestination(MergedAnnotation annotation, MQProperties properties) { - String requestQueue = resolveValueFromAnnotation(annotation, "requestQueue"); - String name = StringUtils.hasText(requestQueue) ? requestQueue : properties.getOutputQueue(); - MQQueueCustomizer customizer = beanFactory.getBean(MQQueueCustomizer.class); - Queue queue = new MQQueue(name); - customizer.customize(queue); - return queue; - } - - private MQListenerConfig validateAnnotationConfig(MergedAnnotation annotation, MQProperties properties, - String className) { - // Annotation property - String concurrencyAnnotation = resolveValueFromAnnotation(annotation, "concurrency"); - String queueCustomizerAnnotation = resolveValueFromAnnotation(annotation, "queueCustomizer"); - String replyQueueTempAnnotation = resolveValueFromAnnotation(annotation, "replyQueueTemp"); - String maxRetriesAnnotation = resolveValueFromAnnotation(annotation, "maxRetries"); - String connectionFactoryAnnotation = resolveValueFromAnnotation(annotation, "connectionFactory"); - - // Resolve dynamic values - int concurrency = Integer.parseInt(concurrencyAnnotation); - MQQueueCustomizer customizer = resolveBeanWithName(queueCustomizerAnnotation, MQQueueCustomizer.class); - String temporaryQueue = resolveQueue(replyQueueTempAnnotation, "", className); - int finalConcurrency = resolveConcurrency(concurrency, properties.getInputConcurrency()); - int maxRetries = resolveRetries(maxRetriesAnnotation); - MQListenerConfig listenerConfig = MQListenerConfig.builder() - .concurrency(finalConcurrency) - .tempQueueAlias(temporaryQueue) - .queue("") - .connectionFactory(connectionFactoryAnnotation) - .customizer(customizer) - .maxRetries(maxRetries) - .build(); - if (!StringUtils.hasText(listenerConfig.getQueue()) && !StringUtils.hasText(listenerConfig.getTempQueueAlias())) { - throw new MQInvalidListenerException("Invalid configuration, should define one of value or tempQueueAlias"); - } - return listenerConfig; - } - - @Override - public Class getObjectType() { - return objectType; - } - - @SuppressWarnings("unchecked") - private ReactiveReplyRouter resolveReplier() { - ResolvableType resolvable = ResolvableType.forClassWithGenerics(ReactiveReplyRouter.class, Message.class); - return (ReactiveReplyRouter) beanFactory.getBeanProvider(resolvable) - .getIfAvailable(ReactiveReplyRouter::new); - } - - private String resolveValueFromAnnotation(MergedAnnotation annotation, String property) { - return embeddedValueResolver.resolveStringValue(annotation.getString(property)); - } - - private T resolveBeanWithName(String beanName, Class tClass) { - if (StringUtils.hasText(beanName)) { - return beanFactory.getBean(beanName, tClass); - } else { - return beanFactory.getBean(tClass); - } - } - - private static class Target implements InvocationHandler { - private final Method matchedMethod; - private final Object targetMethod; - - public Target(Class clazz, Object targetMethod) { - Method required = clazz.getDeclaredMethods()[0]; - Method selected = null; - for (Method method : targetMethod.getClass().getDeclaredMethods()) { - if (matches(required, method)) { - selected = method; - break; - } - } - this.matchedMethod = selected; - this.targetMethod = targetMethod; - } - - @Override - public Object invoke(Object o, Method method, Object[] objects) throws Throwable { - return matchedMethod.invoke(targetMethod, objects); - } - - private static boolean matches(Method required, Method method) { - if (!required.getName().equals(method.getName())) { - return false; - } - if (!required.getReturnType().equals(method.getReturnType())) { - return false; - } - return Arrays.equals(required.getParameterTypes(), method.getParameterTypes()); - } - } - -} - diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/senders/MQAutoconfigurationSender.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/senders/MQAutoconfigurationSender.java new file mode 100644 index 0000000..3ab86d0 --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/senders/MQAutoconfigurationSender.java @@ -0,0 +1,83 @@ +package co.com.bancolombia.commons.jms.mq.config.senders; + +import co.com.bancolombia.commons.jms.api.MQDestinationProvider; +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.api.MQMessageSenderSync; +import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; +import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import co.com.bancolombia.commons.jms.internal.models.MQSenderConfig; +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; +import co.com.bancolombia.commons.jms.mq.config.MQProperties; +import co.com.bancolombia.commons.jms.mq.config.factory.MQSenderFactory; +import jakarta.jms.ConnectionFactory; +import lombok.extern.log4j.Log4j2; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +import static co.com.bancolombia.commons.jms.mq.config.MQProperties.DEFAULT_DOMAIN; + +@Log4j2 +public class MQAutoconfigurationSender { + + @Bean + @Primary + @ConditionalOnMissingBean(MQMessageSender.class) + @ConditionalOnProperty(prefix = "commons.jms", name = "reactive", havingValue = "true") + public MQMessageSender defaultMQMessageSender(ConnectionFactory cf, + MQDestinationProvider provider, + MQProducerCustomizer customizer, + MQProperties properties, + MQHealthListener healthListener, + RetryableConfig retryableConfig, + MQSenderContainer container) { + if (container.containsKey(DEFAULT_DOMAIN)) { + return container.getReactive(DEFAULT_DOMAIN); + } + + MQSenderConfig config = MQSenderConfig.builder() + .connectionFactory(cf) + .concurrency(properties.getOutputConcurrency()) + .destinationProvider(provider) + .producerCustomizer(customizer) + .healthListener(healthListener) + .retryableConfig(retryableConfig) + .build(); + + return (MQMessageSender) MQSenderFactory.fromSenderConfig(DEFAULT_DOMAIN, container, properties, config); + } + + @Bean + @Primary + @ConditionalOnMissingBean(MQMessageSenderSync.class) + @ConditionalOnProperty(prefix = "commons.jms", name = "reactive", havingValue = "false") + public MQMessageSenderSync defaultMQMessageSenderSync(ConnectionFactory cf, + MQDestinationProvider provider, + MQProducerCustomizer customizer, + MQProperties properties, + MQHealthListener healthListener, + RetryableConfig retryableConfig, + MQSenderContainer container) { + if (container.containsKey(DEFAULT_DOMAIN)) { + return container.getImperative(DEFAULT_DOMAIN); + } + + MQSenderConfig config = MQSenderConfig.builder() + .connectionFactory(cf) + .concurrency(properties.getOutputConcurrency()) + .destinationProvider(provider) + .producerCustomizer(customizer) + .healthListener(healthListener) + .retryableConfig(retryableConfig) + .build(); + + return (MQMessageSenderSync) MQSenderFactory.fromSenderConfig(DEFAULT_DOMAIN, container, properties, config); + } + + @Bean + @ConditionalOnMissingBean(MQSenderContainer.class) + public MQSenderContainer defaultMqSenderContainer() { + return new MQSenderContainer(); + } +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/senders/MQSenderContainer.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/senders/MQSenderContainer.java new file mode 100644 index 0000000..d7e8285 --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/senders/MQSenderContainer.java @@ -0,0 +1,25 @@ +package co.com.bancolombia.commons.jms.mq.config.senders; + +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.api.MQMessageSenderSync; +import co.com.bancolombia.commons.jms.mq.config.exceptions.MQInvalidSenderException; + +import java.util.concurrent.ConcurrentHashMap; + +public class MQSenderContainer extends ConcurrentHashMap { + public MQMessageSender getReactive(String domain) { + MQMessageSender res = (MQMessageSender) get(domain); + if (res == null) { + throw new MQInvalidSenderException("Sender for domain " + domain + " could not be found"); + } + return res; + } + + public MQMessageSenderSync getImperative(String domain) { + MQMessageSenderSync res = (MQMessageSenderSync) get(domain); + if (res == null) { + throw new MQInvalidSenderException("Sender for domain " + domain + " could not be found"); + } + return res; + } +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationParser.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationParser.java new file mode 100644 index 0000000..c70b149 --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationParser.java @@ -0,0 +1,43 @@ +package co.com.bancolombia.commons.jms.mq.config.utils; + +import lombok.experimental.UtilityClass; +import org.springframework.core.annotation.MergedAnnotation; +import org.springframework.core.annotation.MergedAnnotation.Adapt; + +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Map; + +@UtilityClass +public class AnnotationParser { + + public static T parseMergedAnnotation(MergedAnnotation mergedAnnotation) { + Map attributes = mergedAnnotation.asMap(Adapt.ANNOTATION_TO_MAP); + return createAnnotationProxy(mergedAnnotation.getType(), attributes); + } + + @SuppressWarnings("unchecked") + private static T createAnnotationProxy(Class annotationType, Map attributes) { + return (T) Proxy.newProxyInstance( + annotationType.getClassLoader(), + new Class[]{annotationType}, + new AnnotationInvocationHandler(attributes) + ); + } + + private static class AnnotationInvocationHandler implements InvocationHandler { + private final Map attributes; + + AnnotationInvocationHandler(Map attributes) { + this.attributes = attributes; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return attributes.get(method.getName()); + } + + } +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationUtils.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationUtils.java index 4c43a5b..5b844a8 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationUtils.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationUtils.java @@ -30,13 +30,13 @@ public static int resolveConcurrency(int concurrencyAnnotation, int concurrencyP return MQProperties.DEFAULT_CONCURRENCY; } - public static String resolveQueue(String primaryAnnotation, String secondaryValue, String queueProperties) { - if (StringUtils.hasText(primaryAnnotation)) { - return primaryAnnotation; + public static String resolve(String fromAnnotation, String defaultValue) { + if (StringUtils.hasText(fromAnnotation)) { + return fromAnnotation; } - if (!StringUtils.hasText(secondaryValue) && StringUtils.hasText(queueProperties)) { - return queueProperties; + if (StringUtils.hasText(defaultValue)) { + return defaultValue; } - return null; + return ""; } } diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/proxy/ReqReplyBeanScanner.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/MQBeanScanner.java similarity index 50% rename from commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/proxy/ReqReplyBeanScanner.java rename to commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/MQBeanScanner.java index 8cc74ab..eda351d 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/proxy/ReqReplyBeanScanner.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/MQBeanScanner.java @@ -1,17 +1,27 @@ -package co.com.bancolombia.commons.jms.mq.config.proxy; +package co.com.bancolombia.commons.jms.mq.config.utils; -import co.com.bancolombia.commons.jms.mq.ReqReply; +import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.lang.NonNull; -public class ReqReplyBeanScanner extends ClassPathBeanDefinitionScanner { - public ReqReplyBeanScanner(BeanDefinitionRegistry registry) { +import java.lang.annotation.Annotation; + +@Log4j2 +public class MQBeanScanner extends ClassPathBeanDefinitionScanner { + private final Class factoryClass; + private final Class annotationClass; + + public MQBeanScanner(BeanDefinitionRegistry registry, + Class annotationClass, Class factoryClass) { super(registry, false); - addIncludeFilter(new AnnotationTypeFilter(ReqReply.class)); + this.factoryClass = factoryClass; + this.annotationClass = annotationClass; + addIncludeFilter(new AnnotationTypeFilter(annotationClass)); } @Override @@ -21,14 +31,12 @@ protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { } @Override - protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) { - beanDefinition.setBeanClassName(getFactoryBeanClassName()); - + protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, @NonNull String beanName) { + log.info("Defining bean factory for {}", beanName); + beanDefinition.setBeanClassName(factoryClass.getName()); beanDefinition.getConstructorArgumentValues() .addGenericArgumentValue(((AnnotatedBeanDefinition) beanDefinition).getMetadata()); - } - - protected String getFactoryBeanClassName() { - return InterfaceComponentProxyFactoryBean.class.getName(); + beanDefinition.getConstructorArgumentValues() + .addGenericArgumentValue(annotationClass); } } diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/MQFactoryBean.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/MQFactoryBean.java new file mode 100644 index 0000000..56e983a --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/config/utils/MQFactoryBean.java @@ -0,0 +1,57 @@ +package co.com.bancolombia.commons.jms.mq.config.utils; + +import co.com.bancolombia.commons.jms.mq.MQSender; +import co.com.bancolombia.commons.jms.mq.ReqReply; +import co.com.bancolombia.commons.jms.mq.config.MQSpringResolver; +import co.com.bancolombia.commons.jms.mq.config.factory.MQReqReplyFactory; +import co.com.bancolombia.commons.jms.mq.config.factory.MQSenderFactory; +import lombok.AllArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.springframework.aop.framework.ProxyFactoryBean; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.core.annotation.MergedAnnotation; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.lang.NonNull; + +import java.lang.annotation.Annotation; + +import static co.com.bancolombia.commons.jms.mq.config.MQAutoconfiguration.CLASS_LOADER_WARN; +import static org.springframework.util.ClassUtils.resolveClassName; + +@Log4j2 +@AllArgsConstructor +public class MQFactoryBean implements FactoryBean { + private final AnnotationMetadata metadata; + private final Class annotationClazz; + private final MQSpringResolver resolver; + + @Override + public Object getObject() { + Class clazz = getObjectType(); + if (!MQFactoryBean.class.getClassLoader().equals(clazz.getClassLoader())) { + log.warn(CLASS_LOADER_WARN); + } + log.info("Creating bean for {} annotated with @{}", clazz.getSimpleName(), annotationClazz.getSimpleName()); + MergedAnnotation mergedAnnotation = metadata.getAnnotations().get(annotationClazz); + T annotation = AnnotationParser.parseMergedAnnotation(mergedAnnotation); + Object target = build(annotation, clazz); + ProxyFactoryBean factoryBean = new ProxyFactoryBean(); + factoryBean.setTarget(target); + factoryBean.setInterfaces(clazz); + return factoryBean.getObject(); + } + + @Override + @NonNull + public Class getObjectType() { + return resolveClassName(metadata.getClassName(), null); + } + + private Object build(T annotation, Class clazz) { + if (annotation instanceof MQSender) { + return MQSenderFactory.fromMQSender((MQSender) annotation, resolver, clazz.getSimpleName()); + } else { + return MQReqReplyFactory.createMQReqReply((ReqReply) annotation, resolver, clazz.getSimpleName()); + } + } +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQExecutorService.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQExecutorService.java new file mode 100644 index 0000000..4117f87 --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQExecutorService.java @@ -0,0 +1,11 @@ +package co.com.bancolombia.commons.jms.mq.listeners; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class MQExecutorService extends ThreadPoolExecutor { + public MQExecutorService(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); + } +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListener.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListener.java index 51bffff..4dcfa69 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListener.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListener.java @@ -1,5 +1,7 @@ package co.com.bancolombia.commons.jms.mq.listeners; +import jakarta.jms.Message; +import jakarta.jms.MessageListener; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import lombok.extern.log4j.Log4j2; @@ -7,8 +9,6 @@ import org.springframework.messaging.handler.invocation.InvocableHandlerMethod; import org.springframework.messaging.support.MessageBuilder; -import jakarta.jms.Message; -import jakarta.jms.MessageListener; import java.lang.reflect.Method; import static com.ibm.msg.client.jakarta.jms.JmsConstants.JMSX_DELIVERY_COUNT; diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListenerRetries.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListenerRetries.java index 199e033..3627abe 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListenerRetries.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListenerRetries.java @@ -1,14 +1,13 @@ package co.com.bancolombia.commons.jms.mq.listeners; +import jakarta.jms.Message; +import jakarta.jms.MessageListener; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import lombok.extern.log4j.Log4j2; import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; -import jakarta.jms.Message; -import jakarta.jms.MessageListener; - import static com.ibm.msg.client.jakarta.jms.JmsConstants.JMSX_DELIVERY_COUNT; @Log4j2 diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQReactiveMessageListener.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQReactiveMessageListener.java index 21ff525..85ec94c 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQReactiveMessageListener.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQReactiveMessageListener.java @@ -1,13 +1,13 @@ package co.com.bancolombia.commons.jms.mq.listeners; +import jakarta.jms.Message; +import jakarta.jms.MessageListener; import lombok.extern.log4j.Log4j2; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.handler.invocation.reactive.InvocableHandlerMethod; import org.springframework.messaging.support.MessageBuilder; import reactor.core.publisher.Mono; -import jakarta.jms.Message; -import jakarta.jms.MessageListener; import java.lang.reflect.Method; @Log4j2 diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplyListener.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplyListener.java index 252bbf5..12c04cb 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplyListener.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplyListener.java @@ -20,20 +20,20 @@ public final class MQRequestReplyListener extends MQMessageListenerRetries imple public static final int SECONDS_TIMEOUT = 30; private final MQMessageSender sender; private final ReactiveReplyRouter router; - private final MQQueuesContainer container; + private final MQQueuesContainer queuesContainer; private final Destination requestQueue; private final String replyQueue; public MQRequestReplyListener(MQMessageSender sender, ReactiveReplyRouter router, - MQQueuesContainer container, + MQQueuesContainer queuesContainer, Destination requestQueue, String replyQueue, int maxRetries) { super(maxRetries); this.sender = sender; this.router = router; - this.container = container; + this.queuesContainer = queuesContainer; this.requestQueue = requestQueue; this.replyQueue = replyQueue; } @@ -61,7 +61,7 @@ public Mono requestReply(MQMessageCreator messageCreator, Duration time private MQMessageCreator defaultCreator(String message) { return ctx -> { Message jmsMessage = ctx.createTextMessage(message); - Queue queue = container.get(replyQueue); + Queue queue = queuesContainer.get(replyQueue); jmsMessage.setJMSReplyTo(queue); if (log.isInfoEnabled() && queue != null) { log.info("Setting queue for reply to: {}", queue.getQueueName()); diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplySelector.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplySelector.java new file mode 100644 index 0000000..933816e --- /dev/null +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplySelector.java @@ -0,0 +1,75 @@ +package co.com.bancolombia.commons.jms.mq.listeners; + +import co.com.bancolombia.commons.jms.api.MQMessageCreator; +import co.com.bancolombia.commons.jms.api.MQMessageSelectorListener; +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.api.MQQueuesContainer; +import co.com.bancolombia.commons.jms.api.MQRequestReply; +import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorBuilder; +import jakarta.jms.Destination; +import jakarta.jms.Message; +import jakarta.jms.Queue; +import lombok.extern.log4j.Log4j2; +import reactor.core.publisher.Mono; + +import java.time.Duration; + +@Log4j2 +public final class MQRequestReplySelector implements MQRequestReply { + public static final int SECONDS_TIMEOUT = 30; + private final MQMessageSender sender; + private final MQQueuesContainer container; + private final Destination requestQueue; + private final String replyQueue; + private final SelectorBuilder selector; + + private final MQMessageSelectorListener listener; + + public MQRequestReplySelector(MQMessageSender sender, + MQQueuesContainer container, + Destination requestQueue, + String replyQueue, + SelectorBuilder selector, + MQMessageSelectorListener listener) { + this.sender = sender; + this.container = container; + this.requestQueue = requestQueue; + this.replyQueue = replyQueue; + this.selector = selector; + this.listener = listener; + } + + @Override + public Mono requestReply(String message) { + return requestReply(defaultCreator(message)); + } + + @Override + public Mono requestReply(String message, Duration timeout) { + return requestReply(defaultCreator(message), timeout); + } + + @Override + public Mono requestReply(MQMessageCreator messageCreator) { + return requestReply(messageCreator, Duration.ofSeconds(SECONDS_TIMEOUT)); + } + + @Override + public Mono requestReply(MQMessageCreator messageCreator, Duration timeout) { + return sender.send(requestQueue, messageCreator) + .flatMap(id -> listener.getMessageBySelector(selector.buildSelector(id), timeout.toMillis(), + container.get(replyQueue))); + } + + private MQMessageCreator defaultCreator(String message) { + return ctx -> { + Message jmsMessage = ctx.createTextMessage(message); + Queue queue = container.get(replyQueue); + jmsMessage.setJMSReplyTo(queue); + if (log.isInfoEnabled() && queue != null) { + log.info("Setting queue for reply to: {}", queue.getQueueName()); + } + return jmsMessage; + }; + } +} diff --git a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/utils/MQUtils.java b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/utils/MQUtils.java index 85b4c73..5c553fd 100644 --- a/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/utils/MQUtils.java +++ b/commons-jms-mq/src/main/java/co/com/bancolombia/commons/jms/mq/utils/MQUtils.java @@ -3,14 +3,14 @@ import com.ibm.mq.jakarta.jms.MQQueue; import com.ibm.msg.client.jakarta.jms.JmsReadablePropertyContext; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.extern.log4j.Log4j2; - import jakarta.jms.JMSContext; import jakarta.jms.JMSException; import jakarta.jms.Queue; import jakarta.jms.TemporaryQueue; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.log4j.Log4j2; + import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAnnotationAutoconfigurationTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAnnotationAutoconfigurationTest.java new file mode 100644 index 0000000..9272c76 --- /dev/null +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAnnotationAutoconfigurationTest.java @@ -0,0 +1,27 @@ +package co.com.bancolombia.commons.jms.mq.config; + +import co.com.bancolombia.commons.jms.mq.config.utils.Utils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class MQAnnotationAutoconfigurationTest { + private final BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); + private MQAnnotationAutoconfiguration annotationAutoconfiguration; + + @BeforeEach + void setup() { + annotationAutoconfiguration = new MQAnnotationAutoconfiguration(); + } + + @Test + void shouldScan() { + annotationAutoconfiguration.registerBeanDefinitions(Utils.getMetadataEnableMQGateway(), registry); + assertTrue(registry.containsBeanDefinition("fixedReqReply")); + assertTrue(registry.containsBeanDefinition("testReqReply")); + assertTrue(registry.containsBeanDefinition("sampleSender")); + } +} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfiguracionTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfiguracionTest.java index 08a7518..9b397f8 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfiguracionTest.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfiguracionTest.java @@ -1,21 +1,32 @@ package co.com.bancolombia.commons.jms.mq.config; import co.com.bancolombia.commons.jms.api.MQBrokerUtils; +import co.com.bancolombia.commons.jms.api.MQDestinationProvider; +import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; +import co.com.bancolombia.commons.jms.api.MQQueueManagerSetter; import co.com.bancolombia.commons.jms.api.MQQueuesContainer; +import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorBuilder; +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; +import co.com.bancolombia.commons.jms.mq.listeners.MQExecutorService; +import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; import com.ibm.mq.jakarta.jms.MQQueue; +import jakarta.jms.JMSContext; +import jakarta.jms.JMSException; +import jakarta.jms.JMSProducer; +import jakarta.jms.Message; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import jakarta.jms.JMSContext; -import jakarta.jms.JMSException; - import static com.ibm.msg.client.jakarta.wmq.common.CommonConstants.WMQ_TARGET_CLIENT; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class MQAutoconfiguracionTest { @@ -24,6 +35,8 @@ class MQAutoconfiguracionTest { private MQQueue queue; @Mock private JMSContext context; + @Mock + private JMSProducer producer; @Test void shouldCreateCustomizer() throws JMSException { @@ -44,4 +57,63 @@ void shouldCreateBrokerUtils() throws JMSException { utils.setQueueManager(context, queue); verify(queue, times(1)).setBaseQueueManagerName(""); } + + @Test + void shouldCreateMQDestinationProvider() { + when(context.createQueue(anyString())).thenReturn(queue); + MQDestinationProvider provider = configuration.defaultMqDestinationProvider( + configuration.defaultMQQueueCustomizer(), MQProperties.builder().outputQueue("sample").build()); + provider.create(context); + verify(context, times(1)).createQueue("sample"); + } + + @Test + void shouldCreateMQProducerCustomizer() { + MQProducerCustomizer customizer = configuration.defaultMQProducerCustomizer(MQProperties.builder() + .producerTtl(5000) + .build()); + customizer.customize(producer); + verify(producer, times(1)).setTimeToLive(5000); + } + + @Test + void shouldCreateMQQueueManagerSetter() throws JMSException { + MQQueueManagerSetter setter = configuration.qmSetter(MQProperties.builder() + .inputQueueSetQueueManager(true) + .inputQueue("sample") + .build(), + configuration.defaultMQQueuesContainer()); + setter.accept(context, queue); + verify(queue, times(1)).setBaseQueueManagerName(""); + } + + @Test + void shouldCreateMQListenerHealthIndicator() { + MQHealthListener bean = configuration.defaultMqHealthListener(); + Assertions.assertNotNull(bean); + } + + @Test + void shouldCreateRetryableConfig() { + RetryableConfig bean = configuration.defaultRetryableConfig(MQProperties.builder().build()); + Assertions.assertNotNull(bean); + } + + @Test + void shouldCreateSelectorBuilder() { + SelectorBuilder bean = configuration.defaultSelectorBuilder(); + Assertions.assertNotNull(bean); + } + + @Test + void shouldCreateMQExecutorService() { + MQExecutorService bean = configuration.defaultMqExecutorService(); + Assertions.assertNotNull(bean); + } + + @Test + void shouldCreateReactiveReplyRouter() { + ReactiveReplyRouter bean = configuration.selectorReactiveReplyRouter(); + Assertions.assertNotNull(bean); + } } diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSelectorListenerTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSelectorListenerTest.java deleted file mode 100644 index 7786282..0000000 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQAutoconfigurationSelectorListenerTest.java +++ /dev/null @@ -1,121 +0,0 @@ -package co.com.bancolombia.commons.jms.mq.config; - -import co.com.bancolombia.commons.jms.api.MQMessageSelectorListenerSync; -import co.com.bancolombia.commons.jms.api.MQQueueManagerSetter; -import co.com.bancolombia.commons.jms.api.MQQueuesContainer; -import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; -import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.ContextPerMessageStrategy; -import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorModeProvider; -import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; -import co.com.bancolombia.commons.jms.mq.config.exceptions.MQInvalidListenerException; -import co.com.bancolombia.commons.jms.mq.helper.JmsContextImpl; -import co.com.bancolombia.commons.jms.utils.MQQueuesContainerImp; -import com.ibm.mq.jakarta.jms.MQQueue; -import com.ibm.msg.client.jakarta.jms.JmsReadablePropertyContext; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import jakarta.jms.ConnectionFactory; -import jakarta.jms.JMSContext; -import jakarta.jms.JMSException; - -import static com.ibm.msg.client.jakarta.wmq.common.CommonConstants.WMQ_RESOLVED_QUEUE_MANAGER; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class MQAutoconfigurationSelectorListenerTest { - @Mock - private ConnectionFactory connectionFactory; - @Mock - private JMSContext context; - @Mock - private JmsReadablePropertyContext propertyContext; - @Mock - private MQHealthListener healthListener; - @Mock - private MQQueue queue; - private final MQAutoconfigurationSelectorListener configurator = new MQAutoconfigurationSelectorListener(); - - @Test - void shouldMapConfiguration() { - // Arrange - int inputConcurrency = 1; - String queueName = "QUEUE"; - MQProperties properties = new MQProperties(); - properties.setInputConcurrency(inputConcurrency); - properties.setInputQueue(queueName); - // Act - MQListenerConfig config = configurator.messageSelectorListenerConfig(properties, null, null); - // Assert - assertEquals(inputConcurrency, config.getConcurrency()); - assertEquals(queueName, config.getQueue()); - } - - @Test - void shouldHandleError() { - // Arrange - MQListenerConfig config = MQListenerConfig.builder().concurrency(0).build(); - MQProperties properties = new MQProperties(); - properties.setMaxRetries(10); - properties.setInitialRetryIntervalMillis(1000); - SelectorModeProvider provider = SelectorModeProvider.defaultSelector(); - // Act - // Assert - assertThrows(MQInvalidListenerException.class, - () -> configurator.defaultMQMultiContextMessageSelectorListenerSync(null, config, healthListener, - properties, provider)); - } - - @Test - void shouldCreateDefaultMessageSelectorListener() { - // Arrange - MQListenerConfig config = MQListenerConfig.builder() - .concurrency(1) - .queue("QUEUE") - .build(); - MQProperties properties = new MQProperties(); - properties.setMaxRetries(10); - properties.setInitialRetryIntervalMillis(1000); - when(connectionFactory.createContext()).thenReturn(context); - when(context.createQueue(anyString())).thenReturn(queue); - // Act - MQMessageSelectorListenerSync listener = configurator. - defaultMQMultiContextMessageSelectorListenerSync(connectionFactory, config, healthListener, - properties, SelectorModeProvider.defaultSelector()); - // Assert - assertNotNull(listener); - } - - @Test - void shouldMapConfigurationWithQueueManager() throws JMSException { - // Arrange - when(propertyContext.getStringProperty(WMQ_RESOLVED_QUEUE_MANAGER)).thenReturn("QM1"); - doReturn(null).when(queue).getBaseQueueManagerName(); - int inputConcurrency = 1; - String queueName = "QUEUE"; - MQProperties properties = new MQProperties(); - properties.setInputConcurrency(inputConcurrency); - properties.setInputQueue(queueName); - properties.setInputQueueSetQueueManager(true); - MQQueuesContainer container = new MQQueuesContainerImp(); - MQQueueManagerSetter setter = configurator.qmSetter(properties, container); - // Act - MQListenerConfig config = configurator.messageSelectorListenerConfig(properties, null, setter); - // Assert - assertEquals(inputConcurrency, config.getConcurrency()); - assertEquals(queueName, config.getQueue()); - config.getQmSetter().accept(new JmsContextImpl(propertyContext), queue); - verify(queue, atLeastOnce()).setBaseQueueManagerName("QM1"); - assertEquals(container.get(queueName), queue); - } - -} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAnnotationProcessorTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAutoconfigurationTest.java similarity index 65% rename from commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAnnotationProcessorTest.java rename to commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAutoconfigurationTest.java index bbf943e..8989ecc 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAnnotationProcessorTest.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQListenerAutoconfigurationTest.java @@ -4,31 +4,33 @@ import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; import co.com.bancolombia.commons.jms.api.MQQueuesContainer; import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; import co.com.bancolombia.commons.jms.mq.MQListener; import co.com.bancolombia.commons.jms.mq.config.exceptions.MQInvalidListenerException; +import jakarta.jms.ConnectionFactory; +import jakarta.jms.JMSException; +import jakarta.jms.Message; import lombok.extern.java.Log; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.stubbing.Answer; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import reactor.core.publisher.Mono; -import jakarta.jms.ConnectionFactory; -import jakarta.jms.JMSException; -import jakarta.jms.Message; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) -class MQListenerAnnotationProcessorTest { +class MQListenerAutoconfigurationTest { @Mock private ConfigurableBeanFactory factory; @Mock @@ -36,32 +38,35 @@ class MQListenerAnnotationProcessorTest { @Mock private ConnectionFactory cf; @Mock + private ConnectionFactory cf2; + @Mock private MQQueueCustomizer customizer; @Mock private MQBrokerUtils brokerUtils; @Mock private MQHealthListener healthListener; + @Mock + private RetryableConfig retryableConfig; + @Mock + private MQSpringResolver resolver; @InjectMocks - private MQListenerAnnotationProcessor processor; + private MQListenerAutoconfiguration processor; @BeforeEach void setup() { - processor.setBeanFactory(factory); - doReturn(customizer).when(factory).getBean(MQQueueCustomizer.class); - when(factory.resolveEmbeddedValue(anyString())) - .thenAnswer((Answer) invocation -> (String) invocation.getArguments()[0]); + doReturn(container).when(resolver).getQueuesContainer(); + doReturn(healthListener).when(resolver).getHealthListener(); + doReturn(brokerUtils).when(resolver).getBrokerUtils(); + doReturn(cf).when(resolver).getConnectionFactory(""); + doAnswer(invocation -> invocation.getArguments()[0]).when(resolver).resolveString(anyString()); } @Test void shouldProcessAnnotated() { // Arrange + doReturn(new MQProperties()).when(resolver).getProperties(); + doReturn(cf2).when(resolver).getConnectionFactory("custom"); Object bean = new MyListener(); - doReturn(new MQProperties()).when(factory).getBean(MQProperties.class); - doReturn(container).when(factory).getBean(MQQueuesContainer.class); - doReturn(healthListener).when(factory).getBean(MQHealthListener.class); - doReturn(brokerUtils).when(factory).getBean(MQBrokerUtils.class); - doReturn(cf).when(factory).getBean(ConnectionFactory.class); - doReturn(cf).when(factory).getBean("custom", ConnectionFactory.class); // Act Object result = processor.postProcessAfterInitialization(bean, "MyListener"); // Assert @@ -74,12 +79,8 @@ void shouldProcessAnnotatedReactive() { Object bean = new MyReactiveListener(); MQProperties properties = new MQProperties(); properties.setReactive(true); - doReturn(properties).when(factory).getBean(MQProperties.class); - doReturn(container).when(factory).getBean(MQQueuesContainer.class); - doReturn(brokerUtils).when(factory).getBean(MQBrokerUtils.class); - doReturn(healthListener).when(factory).getBean(MQHealthListener.class); - doReturn(cf).when(factory).getBean(ConnectionFactory.class); - doReturn(cf).when(factory).getBean("custom", ConnectionFactory.class); + doReturn(new MQProperties()).when(resolver).getProperties(); + doReturn(cf2).when(resolver).getConnectionFactory("custom"); // Act Object result = processor.postProcessAfterInitialization(bean, "MyReactiveListener"); // Assert @@ -92,9 +93,7 @@ void shouldWorksWithInvalidConcurrency() { MQProperties properties = new MQProperties(); properties.setInputConcurrency(0); properties.setReactive(true); - doReturn(properties).when(factory).getBean(MQProperties.class); - doReturn(container).when(factory).getBean(MQQueuesContainer.class); - doReturn(cf).when(factory).getBean(ConnectionFactory.class); + doReturn(new MQProperties()).when(resolver).getProperties(); Object bean = new MyReactiveListenerInvalidConcurrency(); // Act Object result = processor.postProcessAfterInitialization(bean, "MyReactiveListenerInvalidConcurrency"); @@ -102,26 +101,12 @@ void shouldWorksWithInvalidConcurrency() { assertEquals(bean, result); } - @Test - void shouldFailWithInvalidBothQueues() { - // Arrange - MQProperties properties = new MQProperties(); - properties.setReactive(true); - doReturn(properties).when(factory).getBean(MQProperties.class); - Object bean = new MyReactiveListenerInvalidBothQueues(); - // Assert - assertThrows(MQInvalidListenerException.class, () -> { - // Act - processor.postProcessAfterInitialization(bean, "MyReactiveListenerInvalidBothQueues"); - }); - } - @Test void shouldFailWithInvalidNoQueues() { // Arrange MQProperties properties = new MQProperties(); properties.setReactive(true); - doReturn(properties).when(factory).getBean(MQProperties.class); + doReturn(new MQProperties()).when(resolver).getProperties(); Object bean = new MyReactiveListenerInvalidNoQueues(); // Assert assertThrows(MQInvalidListenerException.class, () -> { @@ -165,14 +150,6 @@ public Mono process(Message message) { } } - public static class MyReactiveListenerInvalidBothQueues { - - @MQListener(value = "QUEUE.NAME", tempQueueAlias = "alias") - public Mono process(Message message) { - return Mono.empty(); - } - } - public static class MyReactiveListenerInvalidNoQueues { @MQListener diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/InterfaceComponentProxyFactoryBeanTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQSpringResolverTest.java similarity index 51% rename from commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/InterfaceComponentProxyFactoryBeanTest.java rename to commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQSpringResolverTest.java index 056b287..6c31364 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/InterfaceComponentProxyFactoryBeanTest.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/MQSpringResolverTest.java @@ -1,36 +1,29 @@ -package co.com.bancolombia.commons.jms.mq.config.proxy; +package co.com.bancolombia.commons.jms.mq.config; import co.com.bancolombia.commons.jms.api.MQBrokerUtils; -import co.com.bancolombia.commons.jms.api.MQMessageCreator; -import co.com.bancolombia.commons.jms.api.MQMessageSender; import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; +import co.com.bancolombia.commons.jms.api.MQQueueManagerSetter; import co.com.bancolombia.commons.jms.api.MQQueuesContainer; import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; -import co.com.bancolombia.commons.jms.mq.config.MQProperties; +import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorBuilder; +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; +import co.com.bancolombia.commons.jms.mq.config.senders.MQSenderContainer; +import co.com.bancolombia.commons.jms.mq.listeners.MQExecutorService; import co.com.bancolombia.commons.jms.utils.MQQueuesContainerImp; import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; -import com.ibm.msg.client.jakarta.wmq.compat.jms.internal.JMSC; -import jakarta.jms.JMSContext; +import jakarta.jms.ConnectionFactory; +import jakarta.jms.Message; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.stubbing.Answer; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.ResolvableType; -import org.springframework.core.type.AnnotationMetadata; -import reactor.core.publisher.Mono; -import reactor.test.StepVerifier; - -import jakarta.jms.Connection; -import jakarta.jms.ConnectionFactory; -import jakarta.jms.Destination; -import jakarta.jms.JMSException; -import jakarta.jms.Message; -import jakarta.jms.Session; -import jakarta.jms.TemporaryQueue; +import org.springframework.util.StringValueResolver; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -39,88 +32,98 @@ import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) -class InterfaceComponentProxyFactoryBeanTest { - - @Mock - private ConfigurableBeanFactory beanFactory; - @Mock - private MQMessageSender sender; +class MQSpringResolverTest { @Mock private ConnectionFactory connectionFactory; @Mock private MQHealthListener healthListener; @Mock - private JMSContext context; + private RetryableConfig retryableConfig; + @Mock + private MQExecutorService executor; @Mock - private TemporaryQueue queue; + private MQBrokerUtils brokerUtils; @Mock private ObjectProvider provider; - // @Mock -// private MQMessageSender sender; - private InterfaceComponentProxyFactoryBean factoryBean; + @Mock + private MQSenderContainer senderContainer; + @Mock + private SelectorBuilder selectorBuilder; + @Mock + private BeanFactory beanFactory; + @Mock + private StringValueResolver stringValueResolver; + + private MQSpringResolver resolver; @BeforeEach - void setup() { - AnnotationMetadata metadata = Utils.getMetadataReqReply(); - factoryBean = new InterfaceComponentProxyFactoryBean(metadata); - factoryBean.setBeanFactory(beanFactory); + public void setup(){ + resolver = new MQSpringResolver(beanFactory); + resolver.setEmbeddedValueResolver(stringValueResolver); } - @Test - void shouldReturnObjectType() { - // Arrange - // Act - Class clazz = factoryBean.getObjectType(); - // Assert - assertNotNull(clazz); - assertEquals("TestCustomAnnotation", clazz.getSimpleName()); - } @Test - void shouldInstanceTheBean() throws JMSException { + void shouldInstanceTheBean() { // Arrange when(provider.getIfAvailable(any())).thenReturn(new ReactiveReplyRouter()); when(beanFactory.getBeanProvider(any(ResolvableType.class))).thenReturn(provider); - when(beanFactory.resolveEmbeddedValue(anyString())) + when(stringValueResolver.resolveStringValue(anyString())) .thenAnswer((Answer) invocation -> (String) invocation.getArguments()[0]); when(beanFactory.getBean(any(Class.class))) .thenAnswer(invocation -> { Object arguments = invocation.getArguments()[0]; + if (arguments.equals(MQQueuesContainer.class)) { + return new MQQueuesContainerImp(); + } if (arguments.equals(MQProperties.class)) { return new MQProperties(); } if (arguments.equals(MQBrokerUtils.class)) { - return (MQBrokerUtils) (context, queue) -> { + return brokerUtils; + } + if (arguments.equals(MQHealthListener.class)) { + return healthListener; + } + if (arguments.equals(RetryableConfig.class)) { + return retryableConfig; + } + if (arguments.equals(MQExecutorService.class)) { + return executor; + } + if (arguments.equals(MQQueueManagerSetter.class)) { + return (MQQueueManagerSetter) (tx, queue) -> { }; } if (arguments.equals(MQQueueCustomizer.class)) { return (MQQueueCustomizer) queue -> { }; } - if (arguments.equals(MQQueuesContainer.class)) { - return new MQQueuesContainerImp(); + if (arguments.equals(MQSenderContainer.class)) { + return senderContainer; } - if (arguments.equals(MQMessageSender.class)) { - return sender; + if (arguments.equals(SelectorBuilder.class)) { + return selectorBuilder; } if (arguments.equals(ConnectionFactory.class)) { return connectionFactory; } - if (arguments.equals(MQHealthListener.class)) { - return healthListener; - } return null; }); - // Listener mocks - when(connectionFactory.createContext()).thenReturn(context); - when(context.createTemporaryQueue()).thenReturn(queue); - // Sender Mock - when(sender.send(any(Destination.class), any(MQMessageCreator.class))).thenReturn(Mono.empty()); // Act - TestCustomAnnotation bean = (TestCustomAnnotation) factoryBean.getObject(); // Assert - assertNotNull(bean); - StepVerifier.create(bean.requestReply("Sample")) - .verifyComplete(); + assertNotNull(resolver.getResolver()); + assertNotNull(resolver.getConnectionFactory(null)); + assertNotNull(resolver.getQueuesContainer()); + assertNotNull(resolver.getProperties()); + assertNotNull(resolver.getBrokerUtils()); + assertNotNull(resolver.getHealthListener()); + assertNotNull(resolver.getRetryableConfig()); + assertNotNull(resolver.getMqExecutorService()); + assertNotNull(resolver.getMqQueueManagerSetter()); + assertNotNull(resolver.getMqSenderContainer()); + assertNotNull(resolver.getSelectorBuilder()); + assertNotNull(resolver.resolveReplier()); + assertEquals("JUAN", resolver.resolveString("JUAN")); } } diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/health/MQListenerHealthIndicatorTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/health/MQListenerHealthIndicatorTest.java index 310d01b..0186953 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/health/MQListenerHealthIndicatorTest.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/health/MQListenerHealthIndicatorTest.java @@ -1,13 +1,12 @@ package co.com.bancolombia.commons.jms.mq.config.health; import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import jakarta.jms.JMSException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.Status; -import jakarta.jms.JMSException; - import static org.junit.jupiter.api.Assertions.assertEquals; class MQListenerHealthIndicatorTest { diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/EnableReqReplyRegistrarTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/EnableReqReplyRegistrarTest.java deleted file mode 100644 index 2cfaab8..0000000 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/EnableReqReplyRegistrarTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package co.com.bancolombia.commons.jms.mq.config.proxy; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.beans.factory.support.SimpleBeanDefinitionRegistry; -import org.springframework.context.annotation.ScannedGenericBeanDefinition; -import org.springframework.core.type.AnnotationMetadata; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class EnableReqReplyRegistrarTest { - private final BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); - private EnableReqReplyRegistrar registrar; - - @BeforeEach - void setup() { - registrar = new EnableReqReplyRegistrar(); - } - - @Test - void shouldRegisterBeanDefinition() { - // Arrange - AnnotationMetadata metadata = Utils.getMetadataEnableReqReply(); - // Act - registrar.registerBeanDefinitions(metadata, registry); - // Assert - BeanDefinition definition = registry.getBeanDefinition("request.queue"); - assertEquals("co.com.bancolombia.commons.jms.mq.config.proxy.TestCustomAnnotation", - ((ScannedGenericBeanDefinition) definition).getMetadata().getClassName()); - } - -} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/SampleConfig.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/SampleConfig.java deleted file mode 100644 index 2e25f4b..0000000 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/SampleConfig.java +++ /dev/null @@ -1,9 +0,0 @@ -package co.com.bancolombia.commons.jms.mq.config.proxy; - -import co.com.bancolombia.commons.jms.mq.EnableReqReply; -import org.springframework.context.annotation.Configuration; - -@Configuration -@EnableReqReply -public class SampleConfig { -} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/senders/MQAutoconfigurationSenderTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/senders/MQAutoconfigurationSenderTest.java new file mode 100644 index 0000000..2dc86ac --- /dev/null +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/senders/MQAutoconfigurationSenderTest.java @@ -0,0 +1,77 @@ +package co.com.bancolombia.commons.jms.mq.config.senders; + +import co.com.bancolombia.commons.jms.api.MQDestinationProvider; +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.api.MQMessageSenderSync; +import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; +import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; +import co.com.bancolombia.commons.jms.mq.config.MQProperties; +import jakarta.jms.ConnectionFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MQAutoconfigurationSenderTest { + @Mock + private ConnectionFactory cf; + @Mock + private MQDestinationProvider provider; + @Mock + private MQProducerCustomizer customizer; + @Mock + private MQProperties properties; + @Mock + private MQHealthListener healthListener; + @Mock + private RetryableConfig retryableConfig; + @Mock + private MQSenderContainer container; + private MQAutoconfigurationSender senderConfiguration; + + @BeforeEach + public void setup() { + senderConfiguration = new MQAutoconfigurationSender(); + } + + @Test + void shouldCreateSenderSync() { + // Arrange + // Act + MQMessageSenderSync sender = senderConfiguration.defaultMQMessageSenderSync( + cf, + provider, customizer, + properties, + healthListener, + retryableConfig, + container + ); + // Assert + assertNotNull(sender); + } + + @Test + void shouldCreateSenderAsync() { + // Arrange + when(properties.isReactive()).thenReturn(true); + // Act + MQMessageSender sender = senderConfiguration.defaultMQMessageSender( + cf, + provider, + customizer, + properties, + healthListener, + retryableConfig, + senderConfiguration.defaultMqSenderContainer() + ); + // Assert + assertNotNull(sender); + } +} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/senders/MQSenderContainerTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/senders/MQSenderContainerTest.java new file mode 100644 index 0000000..53ce8a8 --- /dev/null +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/senders/MQSenderContainerTest.java @@ -0,0 +1,68 @@ +package co.com.bancolombia.commons.jms.mq.config.senders; + +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.api.MQMessageSenderSync; +import co.com.bancolombia.commons.jms.mq.config.exceptions.MQInvalidSenderException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static co.com.bancolombia.commons.jms.mq.config.MQProperties.DEFAULT_DOMAIN; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@ExtendWith(MockitoExtension.class) +class MQSenderContainerTest { + @Mock + private MQMessageSender sender; + @Mock + private MQMessageSenderSync senderSync; + private MQSenderContainer senderContainer; + + @BeforeEach + public void setup() { + senderContainer = new MQSenderContainer(); + senderContainer.put(DEFAULT_DOMAIN, sender); + senderContainer.put("other", senderSync); + } + + @Test + void shouldRetrieveSync() { + // Arrange + // Act + MQMessageSenderSync senderImperative = senderContainer.getImperative("other"); + // Assert + assertEquals(senderSync, senderImperative); + } + + @Test + void shouldRetrieve() { + // Arrange + // Act + MQMessageSender senderReactive = senderContainer.getReactive(DEFAULT_DOMAIN); + // Assert + assertEquals(sender, senderReactive); + } + + @Test + void shouldFailWhenNotRetrieveSync() { + // Arrange + // Assert + assertThrows(MQInvalidSenderException.class, () -> { + // Act + senderContainer.getImperative("no-existent"); + }); + } + + @Test + void shouldFailWhenNotRetrieve() { + // Arrange + // Assert + assertThrows(MQInvalidSenderException.class, () -> { + // Act + senderContainer.getReactive("no-existent"); + }); + } +} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationParserTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationParserTest.java new file mode 100644 index 0000000..a8d7f25 --- /dev/null +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationParserTest.java @@ -0,0 +1,67 @@ +package co.com.bancolombia.commons.jms.mq.config.utils; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.core.annotation.MergedAnnotation; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.doReturn; + +@ExtendWith(MockitoExtension.class) +class AnnotationParserTest { + + @Mock + private MergedAnnotation mergedAnnotation; + + @Test + void testParseMergedAnnotation() { + // Define annotation attributes + Map attributes = new HashMap<>(); + attributes.put("value", "TestValue"); + attributes.put("intValue", 123); + + // Stub the behavior of MergedAnnotation + doReturn(attributes).when(mergedAnnotation).asMap(MergedAnnotation.Adapt.ANNOTATION_TO_MAP); + doReturn(TestAnnotation.class).when(mergedAnnotation).getType(); + + // Parse the mergedAnnotation + TestAnnotation annotation = AnnotationParser.parseMergedAnnotation(mergedAnnotation); + + // Verify that the annotation was correctly parsed + assertEquals("TestValue", annotation.value()); + assertEquals(123, annotation.intValue()); + } + + @Test + void testParseMergedAnnotationWithArrayValue() { + // Define annotation attributes with an array value + Map attributes = new HashMap<>(); + attributes.put("arrayValue", new String[]{"A", "B", "C"}); + + // Stub the behavior of MergedAnnotation + doReturn(attributes).when(mergedAnnotation).asMap(MergedAnnotation.Adapt.ANNOTATION_TO_MAP); + doReturn(TestAnnotation.class).when(mergedAnnotation).getType(); + + // Parse the mergedAnnotation + TestAnnotation annotation = AnnotationParser.parseMergedAnnotation(mergedAnnotation); + + // Verify that the annotation was correctly parsed + assertEquals("A", annotation.arrayValue()[0]); + assertEquals("B", annotation.arrayValue()[1]); + assertEquals("C", annotation.arrayValue()[2]); + } + + // Define a custom annotation for testing purposes + public @interface TestAnnotation { + String value(); + + int intValue(); + + String[] arrayValue() default {}; + } +} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationUtilsTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationUtilsTest.java index f9190d2..5e5cf79 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationUtilsTest.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/AnnotationUtilsTest.java @@ -4,7 +4,6 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; class AnnotationUtilsTest { @@ -27,9 +26,9 @@ void shouldResolveConcurrency() { @Test void shouldResolveQueue() { - assertEquals("Q1", AnnotationUtils.resolveQueue("Q1", "Q2", "Q3")); - assertNull(AnnotationUtils.resolveQueue("", "Q2", "Q3")); - assertNull(AnnotationUtils.resolveQueue("", "", "")); - assertEquals("Q3", AnnotationUtils.resolveQueue("", "", "Q3")); + assertEquals("Q1", AnnotationUtils.resolve("Q1", "Q2")); + assertEquals("Q2", AnnotationUtils.resolve("", "Q2")); + assertEquals("", AnnotationUtils.resolve("", "")); + assertEquals("", AnnotationUtils.resolve(null, "")); } } diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/ReqReplyBeanScannerTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/MQBeanScannerTest.java similarity index 61% rename from commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/ReqReplyBeanScannerTest.java rename to commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/MQBeanScannerTest.java index 8ac0639..2e5b8e3 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/ReqReplyBeanScannerTest.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/MQBeanScannerTest.java @@ -1,5 +1,8 @@ -package co.com.bancolombia.commons.jms.mq.config.proxy; +package co.com.bancolombia.commons.jms.mq.config.utils; +import co.com.bancolombia.commons.jms.mq.ReqReply; +import co.com.bancolombia.commons.jms.mq.config.utils.MQBeanScanner; +import co.com.bancolombia.commons.jms.mq.config.utils.MQFactoryBean; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.config.BeanDefinition; @@ -9,20 +12,20 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -class ReqReplyBeanScannerTest { +class MQBeanScannerTest { private final BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); - private ReqReplyBeanScanner beanScanner; + private MQBeanScanner beanScanner; @BeforeEach void setup() { - beanScanner = new ReqReplyBeanScanner(registry); + beanScanner = new MQBeanScanner(registry, ReqReply.class, MQFactoryBean.class); } @Test void shouldScanBeans() { - beanScanner.scan("co.com.bancolombia.commons.jms.mq.config.proxy"); - BeanDefinition definition = registry.getBeanDefinition("request.queue"); - assertEquals("co.com.bancolombia.commons.jms.mq.config.proxy.TestCustomAnnotation", + beanScanner.scan("co.com.bancolombia.commons.jms.mq.config.utils.sample"); + BeanDefinition definition = registry.getBeanDefinition("testReqReply"); + assertEquals("co.com.bancolombia.commons.jms.mq.config.utils.sample.TestReqReply", ((ScannedGenericBeanDefinition) definition).getMetadata().getClassName()); } diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/MQFactoryBeanTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/MQFactoryBeanTest.java new file mode 100644 index 0000000..073d592 --- /dev/null +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/MQFactoryBeanTest.java @@ -0,0 +1,133 @@ +package co.com.bancolombia.commons.jms.mq.config.utils; + +import co.com.bancolombia.commons.jms.api.MQBrokerUtils; +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.api.MQMessageSenderSync; +import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; +import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; +import co.com.bancolombia.commons.jms.api.MQRequestReply; +import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorBuilder; +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; +import co.com.bancolombia.commons.jms.mq.ReqReply; +import co.com.bancolombia.commons.jms.mq.config.MQProperties; +import co.com.bancolombia.commons.jms.mq.config.MQSpringResolver; +import co.com.bancolombia.commons.jms.mq.config.senders.MQSenderContainer; +import co.com.bancolombia.commons.jms.mq.config.utils.sample.SampleConfig; +import co.com.bancolombia.commons.jms.mq.listeners.MQExecutorService; +import co.com.bancolombia.commons.jms.utils.MQQueuesContainerImp; +import jakarta.jms.ConnectionFactory; +import jakarta.jms.JMSConsumer; +import jakarta.jms.JMSContext; +import jakarta.jms.JMSException; +import jakarta.jms.JMSProducer; +import jakarta.jms.TemporaryQueue; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.stubbing.Answer; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.util.StringValueResolver; + +import java.lang.annotation.Annotation; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MQFactoryBeanTest { + private final RetryableConfig retryableConfig = RetryableConfig.builder().build(); + private final MQSenderContainer senderContainer = new MQSenderContainer(); + @Mock + private ConnectionFactory connectionFactory; + @Mock + private MQHealthListener healthListener; + @Mock + private MQExecutorService executor; + @Mock + private MQBrokerUtils brokerUtils; + @Mock + private ObjectProvider provider; + @Mock + private MQMessageSenderSync senderSync; + @Mock + private MQMessageSender sender; + @Mock + private SelectorBuilder selectorBuilder; + @Mock + private StringValueResolver stringValueResolver; + @Mock + private MQSpringResolver resolver; + @Mock + private JMSContext context; + @Mock + private JMSProducer producer; + @Mock + private JMSConsumer consumer; + @Mock + private TemporaryQueue tempQueue; + private MQFactoryBean scanner; + + void setup(AnnotationMetadata metadata, Class annotation) { + when(resolver.resolveString(anyString())) + .thenAnswer((Answer) invocation -> (String) invocation.getArguments()[0]); + when(resolver.getBrokerUtils()).thenReturn(brokerUtils); + when(resolver.getRetryableConfig()).thenReturn(retryableConfig); + when(resolver.getHealthListener()).thenReturn(healthListener); + when(resolver.getMqSenderContainer()).thenReturn(senderContainer); + when(resolver.resolveBean("", MQQueueCustomizer.class)).thenReturn(queue -> { + }); + when(resolver.resolveBean("", MQProducerCustomizer.class)).thenReturn(producer -> { + }); + when(resolver.resolveBean("", RetryableConfig.class)).thenReturn(retryableConfig); + when(resolver.getConnectionFactory(anyString())).thenReturn(connectionFactory); + when(resolver.getQueuesContainer()).thenReturn(new MQQueuesContainerImp()); + scanner = new MQFactoryBean<>(metadata, annotation, resolver); + +// when(provider.getIfAvailable(any())).thenReturn(new ReactiveReplyRouter()); + +// when(resolver.getProvider(any())).thenReturn(provider); +// when(resolver.getResolver()).thenReturn(stringValueResolver); +// when(resolver.getMqExecutorService()).thenReturn(executor); +// when(resolver.getSelectorBuilder()).thenReturn(selectorBuilder); +// when(resolver.getMqQueueManagerSetter()).thenReturn((tx, queue) -> { +// }); + } + + @Test + void shouldCreateTempReqReplyInstance() throws JMSException { + // Arrange + setup(Utils.getMetadataReqReply(), ReqReply.class); + when(resolver.getProperties()).thenReturn(MQProperties.builder().reactive(true).build()); + when(resolver.resolveBean(MQMessageSender.class)).thenReturn(sender); + when(connectionFactory.createContext()).thenReturn(context); + when(context.createProducer()).thenReturn(producer); + when(context.createConsumer(any())).thenReturn(consumer); + when(context.createTemporaryQueue()).thenReturn(tempQueue); + when(tempQueue.getQueueName()).thenReturn("MQ-TEMP-QUEUE"); + // Act + Object generated = scanner.getObject(); + // Assert + assertTrue(generated instanceof MQRequestReply); + } + + @Test + void shouldCreateFixedReqReplyInstance() { + // Arrange + setup(Utils.getMetadataReqReplyFixed(), ReqReply.class); + when(resolver.getProperties()).thenReturn(MQProperties.builder().reactive(true).build()); + when(resolver.resolveBean(MQMessageSender.class)).thenReturn(sender); + when(connectionFactory.createContext()).thenReturn(context); + when(context.createProducer()).thenReturn(producer); + when(context.createQueue(anyString())).thenReturn(tempQueue); + // Act + Object generated = scanner.getObject(); + // Assert + assertTrue(generated instanceof MQRequestReply); + } +} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/Utils.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/Utils.java similarity index 54% rename from commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/Utils.java rename to commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/Utils.java index fed6958..d304f5f 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/Utils.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/Utils.java @@ -1,5 +1,6 @@ -package co.com.bancolombia.commons.jms.mq.config.proxy; +package co.com.bancolombia.commons.jms.mq.config.utils; +import co.com.bancolombia.commons.jms.mq.ReqReply; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.springframework.beans.factory.config.BeanDefinition; @@ -11,19 +12,27 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Utils { - public static AnnotationMetadata getMetadataEnableReqReply() { + public static AnnotationMetadata getMetadataEnableMQGateway() { BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry); - scanner.scan("co.com.bancolombia.commons.jms.mq.config.proxy"); + scanner.scan("co.com.bancolombia.commons.jms.mq.config.utils.sample"); BeanDefinition definition = registry.getBeanDefinition("sampleConfig"); return ((ScannedGenericBeanDefinition) definition).getMetadata(); } public static AnnotationMetadata getMetadataReqReply() { BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); - ClassPathBeanDefinitionScanner scanner = new ReqReplyBeanScanner(registry); - scanner.scan("co.com.bancolombia.commons.jms.mq.config.proxy"); - BeanDefinition definition = registry.getBeanDefinition("request.queue"); + ClassPathBeanDefinitionScanner scanner = new MQBeanScanner(registry, ReqReply.class, MQFactoryBean.class); + scanner.scan("co.com.bancolombia.commons.jms.mq.config.utils.sample"); + BeanDefinition definition = registry.getBeanDefinition("testReqReply"); + return ((ScannedGenericBeanDefinition) definition).getMetadata(); + } + + public static AnnotationMetadata getMetadataReqReplyFixed() { + BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry(); + ClassPathBeanDefinitionScanner scanner = new MQBeanScanner(registry, ReqReply.class, MQFactoryBean.class); + scanner.scan("co.com.bancolombia.commons.jms.mq.config.utils.sample"); + BeanDefinition definition = registry.getBeanDefinition("fixedReqReply"); return ((ScannedGenericBeanDefinition) definition).getMetadata(); } } diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/FixedReqReply.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/FixedReqReply.java new file mode 100644 index 0000000..6778e15 --- /dev/null +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/FixedReqReply.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020-2022 Pavel Grigorev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package co.com.bancolombia.commons.jms.mq.config.utils.sample; + +import co.com.bancolombia.commons.jms.api.MQRequestReply; +import co.com.bancolombia.commons.jms.mq.ReqReply; + +import static co.com.bancolombia.commons.jms.internal.models.MQListenerConfig.QueueType.FIXED; + +@ReqReply(requestQueue = "request.queue", replyQueue = "reply.queue", queueType = FIXED) +public interface FixedReqReply extends MQRequestReply { +} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/SampleConfig.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/SampleConfig.java new file mode 100644 index 0000000..0a8175d --- /dev/null +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/SampleConfig.java @@ -0,0 +1,9 @@ +package co.com.bancolombia.commons.jms.mq.config.utils.sample; + +import co.com.bancolombia.commons.jms.mq.EnableMQGateway; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableMQGateway(scanBasePackages = "co.com.bancolombia.commons.jms.mq.config.utils.sample") +public class SampleConfig { +} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/SampleSender.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/SampleSender.java new file mode 100644 index 0000000..96e73c4 --- /dev/null +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/SampleSender.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020-2022 Pavel Grigorev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package co.com.bancolombia.commons.jms.mq.config.utils.sample; + +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.mq.MQSender; + +@MQSender(destinationQueue = "sample-queue") +public interface SampleSender extends MQMessageSender { +} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/TestCustomAnnotation.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/TestReqReply.java similarity index 77% rename from commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/TestCustomAnnotation.java rename to commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/TestReqReply.java index 9848974..8318809 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/proxy/TestCustomAnnotation.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/config/utils/sample/TestReqReply.java @@ -14,14 +14,11 @@ * limitations under the License. */ -package co.com.bancolombia.commons.jms.mq.config.proxy; +package co.com.bancolombia.commons.jms.mq.config.utils.sample; +import co.com.bancolombia.commons.jms.api.MQRequestReply; import co.com.bancolombia.commons.jms.mq.ReqReply; -import reactor.core.publisher.Mono; - -import jakarta.jms.Message; @ReqReply(requestQueue = "request.queue") -public interface TestCustomAnnotation { - Mono requestReply(String message); +public interface TestReqReply extends MQRequestReply { } diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/helper/JmsContextImpl.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/helper/JmsContextImpl.java index fda9cef..50b19d7 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/helper/JmsContextImpl.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/helper/JmsContextImpl.java @@ -1,8 +1,6 @@ package co.com.bancolombia.commons.jms.mq.helper; import com.ibm.msg.client.jakarta.jms.JmsReadablePropertyContext; -import lombok.AllArgsConstructor; - import jakarta.jms.BytesMessage; import jakarta.jms.ConnectionMetaData; import jakarta.jms.Destination; @@ -20,6 +18,8 @@ import jakarta.jms.TemporaryTopic; import jakarta.jms.TextMessage; import jakarta.jms.Topic; +import lombok.AllArgsConstructor; + import java.io.Serializable; @AllArgsConstructor diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListenerTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListenerTest.java index b3b2bea..e92d602 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListenerTest.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQMessageListenerTest.java @@ -1,5 +1,7 @@ package co.com.bancolombia.commons.jms.mq.listeners; +import jakarta.jms.JMSException; +import jakarta.jms.Message; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -8,9 +10,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.messaging.handler.invocation.InvocableHandlerMethod; -import jakarta.jms.JMSException; -import jakarta.jms.Message; - import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.times; diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQReactiveMessageListenerTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQReactiveMessageListenerTest.java index 2083dc2..59afd49 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQReactiveMessageListenerTest.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQReactiveMessageListenerTest.java @@ -1,5 +1,7 @@ package co.com.bancolombia.commons.jms.mq.listeners; +import jakarta.jms.JMSException; +import jakarta.jms.Message; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -8,10 +10,10 @@ import org.springframework.messaging.handler.invocation.reactive.InvocableHandlerMethod; import reactor.core.publisher.Mono; -import jakarta.jms.JMSException; -import jakarta.jms.Message; +import java.lang.reflect.Method; import static com.ibm.msg.client.jakarta.jms.JmsConstants.JMSX_DELIVERY_COUNT; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.any; import static org.mockito.Mockito.times; @@ -22,6 +24,10 @@ class MQReactiveMessageListenerTest { @Mock private InvocableHandlerMethod handlerMethod; +// @Mock +// private Object bean; +// @Mock +// private Method method; @Mock private Message message; private MQReactiveMessageListener listener; @@ -41,6 +47,15 @@ void shouldListen() { verify(handlerMethod, times(1)).invoke(any(), any(Message.class)); } +// @Test +// void shouldCreateFromBean() { +// // Arrange +// // Act +// MQReactiveMessageListener listener1 = MQReactiveMessageListener.fromBeanAndMethod(bean, method, 1); +// // Assert +// assertNotNull(listener1); +// } + @Test void shouldThrowError() throws JMSException { // Arrange diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplyListenerTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplyListenerTest.java index 717cefe..9242427 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplyListenerTest.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplyListenerTest.java @@ -5,6 +5,12 @@ import co.com.bancolombia.commons.jms.api.MQQueuesContainer; import co.com.bancolombia.commons.jms.utils.MQQueuesContainerImp; import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; +import jakarta.jms.Destination; +import jakarta.jms.JMSContext; +import jakarta.jms.JMSException; +import jakarta.jms.Message; +import jakarta.jms.Queue; +import jakarta.jms.TextMessage; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -14,12 +20,6 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import jakarta.jms.Destination; -import jakarta.jms.JMSContext; -import jakarta.jms.JMSException; -import jakarta.jms.Message; -import jakarta.jms.Queue; -import jakarta.jms.TextMessage; import java.time.Duration; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -91,7 +91,7 @@ void shouldCreateDefaultMessageCreator() throws JMSException { assertEquals(message, createdMessage); } - @Test() + @Test void shouldNotFailWhenNoRelatedMessage() throws JMSException { // Arrange when(message.getJMSCorrelationID()).thenReturn("non-existing-id"); diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplySelectorTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplySelectorTest.java new file mode 100644 index 0000000..73eb821 --- /dev/null +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/listeners/MQRequestReplySelectorTest.java @@ -0,0 +1,108 @@ +package co.com.bancolombia.commons.jms.mq.listeners; + +import co.com.bancolombia.commons.jms.api.MQMessageCreator; +import co.com.bancolombia.commons.jms.api.MQMessageSelectorListener; +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.api.MQQueuesContainer; +import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorBuilder; +import co.com.bancolombia.commons.jms.utils.MQQueuesContainerImp; +import jakarta.jms.Destination; +import jakarta.jms.JMSContext; +import jakarta.jms.JMSException; +import jakarta.jms.Message; +import jakarta.jms.Queue; +import jakarta.jms.TextMessage; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.time.Duration; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MQRequestReplySelectorTest { + @Mock + private TextMessage message; + @Mock + private Queue destination; + @Mock + private JMSContext context; + @Mock + private MQMessageSender sender; + @Mock + private MQMessageSelectorListener listener; + private MQRequestReplySelector reqReply; + + @BeforeEach + public void setup() { + String destinationQueue = "sample"; + String replyQueue = "sample"; + MQQueuesContainer container = new MQQueuesContainerImp(); + container.registerQueue(destinationQueue, destination); + container.registerQueue(replyQueue, destination); + reqReply = new MQRequestReplySelector( + sender, + container, + destination, + replyQueue, + SelectorBuilder.ofDefaults(), + listener + ); + } + + @Test + void shouldSendAndGetReplyFromFixed() { + // Arrange + when(sender.send(any(Destination.class), any(MQMessageCreator.class))).thenReturn(Mono.just("id")); + when(listener.getMessageBySelector(anyString(), anyLong(), any(Destination.class))).thenReturn(Mono.just(message)); + // Act + Mono reply = reqReply.requestReply("MyMessage"); + // Assert + StepVerifier.create(reply) + .assertNext(message1 -> assertEquals(message, message1)) + .verifyComplete(); + } + + @Test + void shouldReplyWithTimeoutFromFixed() { + // Arrange + when(sender.send(any(Destination.class), any(MQMessageCreator.class))).thenReturn(Mono.just("id")); + when(listener.getMessageBySelector(anyString(), anyLong(), any(Destination.class))).thenReturn(Mono.just(message)); + Duration duration = Duration.ofMillis(200); + // Act + Mono reply = reqReply.requestReply("MyMessage", duration); + // Assert + StepVerifier.create(reply) + .assertNext(message1 -> assertEquals(message, message1)) + .verifyComplete(); + } + + @Test + void shouldCreateDefaultMessageCreatorFromFixed() throws JMSException { + // Arrange + ArgumentCaptor creatorArgumentCaptor = ArgumentCaptor.forClass(MQMessageCreator.class); + when(sender.send(eq(destination), creatorArgumentCaptor.capture())).thenReturn(Mono.just("id")); + when(listener.getMessageBySelector(anyString(), anyLong(), any(Destination.class))).thenReturn(Mono.just(message)); + when(context.createTextMessage("MyMessage")).thenReturn(message); + Duration duration = Duration.ofMillis(200); + // Act + Mono reply = reqReply.requestReply("MyMessage", duration); + // Assert + StepVerifier.create(reply).expectNext(message).verifyComplete(); + MQMessageCreator creator = creatorArgumentCaptor.getValue(); + Message createdMessage = creator.create(context); + assertEquals(message, createdMessage); + } + +} diff --git a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/utils/MQUtilsTest.java b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/utils/MQUtilsTest.java index f871548..3830e96 100644 --- a/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/utils/MQUtilsTest.java +++ b/commons-jms-mq/src/test/java/co/com/bancolombia/commons/jms/mq/utils/MQUtilsTest.java @@ -3,17 +3,16 @@ import co.com.bancolombia.commons.jms.mq.helper.JmsContextImpl; import com.ibm.mq.jakarta.jms.MQQueue; import com.ibm.msg.client.jakarta.jms.JmsReadablePropertyContext; +import jakarta.jms.JMSContext; +import jakarta.jms.JMSException; +import jakarta.jms.JMSRuntimeException; +import jakarta.jms.TemporaryQueue; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import jakarta.jms.JMSContext; -import jakarta.jms.JMSException; -import jakarta.jms.JMSRuntimeException; -import jakarta.jms.TemporaryQueue; - import static com.ibm.msg.client.jakarta.wmq.common.CommonConstants.WMQ_RESOLVED_QUEUE_MANAGER; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.doReturn; diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/MQContextListener.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/MQContextListener.java index 4e6c3dc..579c93c 100644 --- a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/MQContextListener.java +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/MQContextListener.java @@ -5,12 +5,10 @@ import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; import co.com.bancolombia.commons.jms.internal.reconnect.AbstractJMSReconnectable; import co.com.bancolombia.commons.jms.utils.MQQueueUtils; -import jakarta.jms.ConnectionFactory; import jakarta.jms.Destination; import jakarta.jms.JMSConsumer; import jakarta.jms.JMSContext; import jakarta.jms.JMSException; -import jakarta.jms.MessageListener; import jakarta.jms.Queue; import jakarta.jms.TemporaryQueue; import lombok.experimental.SuperBuilder; @@ -19,12 +17,9 @@ @Log4j2 @SuperBuilder public class MQContextListener extends AbstractJMSReconnectable { - private final ConnectionFactory connectionFactory; - private final MessageListener listener; - private final MQListenerConfig config; + private final MQListenerConfig listenerConfig; private final MQQueuesContainer container; private final MQBrokerUtils utils; - private final boolean temporary; private JMSConsumer consumer; private JMSContext context; private TemporaryQueue tempQueue; @@ -33,10 +28,10 @@ public class MQContextListener extends AbstractJMSReconnectable implements MQMessageSelectorListenerSync { public static final long DEFAULT_TIMEOUT = 5000L; - private final ConnectionFactory connectionFactory; private final MQListenerConfig config; private final SelectorModeProvider selectorModeProvider; + private final MQQueuesContainer container; private SelectorStrategy strategy; private Destination destination; @@ -43,10 +43,11 @@ protected MQContextMessageSelectorListenerSync connect() { synchronized (this) { if (handled > lastSuccess.get()) { log.info("Starting listener {}", getProcess()); - JMSContext context = connectionFactory.createContext(); + JMSContext context = config.getConnectionFactory().createContext(); context.setExceptionListener(this); destination = MQQueueUtils.setupFixedQueue(context, config); - strategy = selectorModeProvider.get(connectionFactory, context); + container.registerQueue(config.getListeningQueue(), (Queue) destination); + strategy = selectorModeProvider.get(config.getConnectionFactory(), context); log.info("Listener {} started successfully", getProcess()); lastSuccess.set(System.currentTimeMillis()); } else { diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerSync.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerSync.java index 8804b0f..3398dee 100644 --- a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerSync.java +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerSync.java @@ -1,11 +1,11 @@ package co.com.bancolombia.commons.jms.internal.listener.selector; import co.com.bancolombia.commons.jms.api.MQMessageSelectorListenerSync; +import co.com.bancolombia.commons.jms.api.MQQueuesContainer; import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorModeProvider; import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; -import jakarta.jms.ConnectionFactory; import jakarta.jms.Destination; import jakarta.jms.Message; @@ -14,31 +14,21 @@ import java.util.stream.IntStream; public class MQMultiContextMessageSelectorListenerSync implements MQMessageSelectorListenerSync { - private final ConnectionFactory connectionFactory; - private final MQListenerConfig config; - private final MQHealthListener healthListener; - private List adapterList; - private final RetryableConfig retryableConfig; - private final SelectorModeProvider selectorModeProvider; + private final int concurrency; + private final List adapterList; - public MQMultiContextMessageSelectorListenerSync(ConnectionFactory connectionFactory, MQListenerConfig config, - MQHealthListener healthListener, RetryableConfig retryableConfig, SelectorModeProvider selectorModeProvider) { - this.connectionFactory = connectionFactory; - this.config = config; - this.healthListener = healthListener; - this.retryableConfig = retryableConfig; - this.selectorModeProvider = selectorModeProvider; - start(); - } - - public void start() { + public MQMultiContextMessageSelectorListenerSync(MQListenerConfig config, + MQHealthListener healthListener, RetryableConfig retryableConfig, + SelectorModeProvider selectorModeProvider, + MQQueuesContainer container) { + this.concurrency = config.getConcurrency(); adapterList = IntStream.range(0, config.getConcurrency()) .mapToObj(idx -> MQContextMessageSelectorListenerSync.builder() - .connectionFactory(connectionFactory) .config(config) .healthListener(healthListener) .retryableConfig(retryableConfig) .selectorModeProvider(selectorModeProvider) + .container(container) .build() .call()) .collect(Collectors.toList()); @@ -73,7 +63,7 @@ public Message getMessageBySelector(String selector, long timeout, Destination d } protected MQMessageSelectorListenerSync getRandom() { - int selectIndex = (int) (System.currentTimeMillis() % config.getConcurrency()); + int selectIndex = (int) (System.currentTimeMillis() % concurrency); return adapterList.get(selectIndex); } diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/selector/strategy/SelectorBuilder.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/selector/strategy/SelectorBuilder.java new file mode 100644 index 0000000..4a423e1 --- /dev/null +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/listener/selector/strategy/SelectorBuilder.java @@ -0,0 +1,9 @@ +package co.com.bancolombia.commons.jms.internal.listener.selector.strategy; + +public interface SelectorBuilder { + String buildSelector(String correlationId); + + static SelectorBuilder ofDefaults() { + return correlationId -> "JMSCorrelationID='" + correlationId + "'"; + } +} diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQListenerConfig.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQListenerConfig.java index 9128970..1d656ed 100644 --- a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQListenerConfig.java +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQListenerConfig.java @@ -2,34 +2,36 @@ import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; import co.com.bancolombia.commons.jms.api.MQQueueManagerSetter; +import jakarta.jms.ConnectionFactory; +import jakarta.jms.MessageListener; import lombok.Builder; import lombok.Getter; @Getter @Builder(toBuilder = true) public class MQListenerConfig { + private final ConnectionFactory connectionFactory; + private final int concurrency; + private final MessageListener messageListener; + private final MQQueueCustomizer queueCustomizer; + private final String listeningQueue; @Builder.Default - private final String queue = ""; //NOSONAR - @Builder.Default - private final int concurrency = 1; //NOSONAR - @Builder.Default - private final String connectionFactory = ""; //NOSONAR - @Builder.Default - private final String tempQueueAlias = ""; //NOSONAR - @Builder.Default - private final MQQueueCustomizer customizer = ignored -> { //NOSONAR - }; + private final QueueType queueType = QueueType.FIXED; //NOSONAR @Builder.Default private final int maxRetries = -1; //NOSONAR @Builder.Default private final MQQueueManagerSetter qmSetter = (ctx, queueName) -> { }; //NOSONAR - @Builder.Default - SelectorMode selectorMode = SelectorMode.CONTEXT_SHARED; + private final SelectorMode selectorMode = SelectorMode.CONTEXT_SHARED; public enum SelectorMode { CONTEXT_SHARED, CONTEXT_PER_MESSAGE } + + public enum QueueType { + FIXED, + TEMPORARY + } } diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQReqReplyConfig.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQReqReplyConfig.java new file mode 100644 index 0000000..611f72c --- /dev/null +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQReqReplyConfig.java @@ -0,0 +1,41 @@ +package co.com.bancolombia.commons.jms.internal.models; + +import co.com.bancolombia.commons.jms.api.MQQueueCustomizer; +import co.com.bancolombia.commons.jms.api.MQQueueManagerSetter; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder(toBuilder = true) +public class MQReqReplyConfig { + @Builder.Default + private final String requestQueue = ""; //NOSONAR + @Builder.Default + private final String replyQueue = ""; //NOSONAR + @Builder.Default + private final int concurrency = 1; //NOSONAR + @Builder.Default + private final String connectionFactory = ""; //NOSONAR + @Builder.Default + private final MQQueueCustomizer customizer = ignored -> { //NOSONAR + }; + @Builder.Default + private final MQQueueManagerSetter qmSetter = (ctx, queueName) -> { + }; //NOSONAR + + @Builder.Default + SelectorMode selectorMode = SelectorMode.CONTEXT_SHARED; + + @Builder.Default + ReplyMode replyMode = ReplyMode.TEMPORARY_QUEUE; + + public enum SelectorMode { + CONTEXT_SHARED, + CONTEXT_PER_MESSAGE + } + + public enum ReplyMode { + SELECTOR, + TEMPORARY_QUEUE + } +} diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQSenderConfig.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQSenderConfig.java new file mode 100644 index 0000000..3cb710a --- /dev/null +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/models/MQSenderConfig.java @@ -0,0 +1,19 @@ +package co.com.bancolombia.commons.jms.internal.models; + +import co.com.bancolombia.commons.jms.api.MQDestinationProvider; +import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; +import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import jakarta.jms.ConnectionFactory; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder(toBuilder = true) +public class MQSenderConfig { + private final ConnectionFactory connectionFactory; + private final MQDestinationProvider destinationProvider; + private final MQHealthListener healthListener; + private final RetryableConfig retryableConfig; + private final MQProducerCustomizer producerCustomizer; + private final int concurrency; +} diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQContextSenderSync.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQContextSenderSync.java index 1c5f9a1..250da4c 100644 --- a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQContextSenderSync.java +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQContextSenderSync.java @@ -1,12 +1,9 @@ package co.com.bancolombia.commons.jms.internal.sender; -import co.com.bancolombia.commons.jms.api.MQDestinationProvider; import co.com.bancolombia.commons.jms.api.MQMessageCreator; import co.com.bancolombia.commons.jms.api.MQMessageSenderSync; -import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; +import co.com.bancolombia.commons.jms.internal.models.MQSenderConfig; import co.com.bancolombia.commons.jms.internal.reconnect.AbstractJMSReconnectable; -import co.com.bancolombia.commons.jms.utils.MQQueueUtils; -import jakarta.jms.ConnectionFactory; import jakarta.jms.Destination; import jakarta.jms.JMSContext; import jakarta.jms.JMSException; @@ -19,9 +16,7 @@ @Log4j2 @SuperBuilder public class MQContextSenderSync extends AbstractJMSReconnectable implements MQMessageSenderSync { - private final ConnectionFactory connectionFactory; - private final MQDestinationProvider provider; - private final MQProducerCustomizer customizer; + private final MQSenderConfig senderConfig; private JMSContext context; private JMSProducer producer; @@ -44,11 +39,11 @@ protected MQContextSenderSync connect() { synchronized (this) { if (handled > lastSuccess.get()) { log.info("Starting sender {}", getProcess()); - this.context = connectionFactory.createContext(); + this.context = senderConfig.getConnectionFactory().createContext(); this.context.setExceptionListener(this); this.producer = context.createProducer(); - customizer.customize(producer); - this.defaultDestination = provider.create(context); + senderConfig.getProducerCustomizer().customize(producer); + this.defaultDestination = senderConfig.getDestinationProvider().create(context); log.info("Sender {} started successfully", getProcess()); lastSuccess.set(System.currentTimeMillis()); } else { diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQDomainContextSender.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQDomainContextSender.java new file mode 100644 index 0000000..70b1be8 --- /dev/null +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQDomainContextSender.java @@ -0,0 +1,30 @@ +package co.com.bancolombia.commons.jms.internal.sender; + +import co.com.bancolombia.commons.jms.api.MQDomainMessageSender; +import co.com.bancolombia.commons.jms.api.MQMessageCreator; +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import jakarta.jms.Destination; +import lombok.AllArgsConstructor; +import reactor.core.publisher.Mono; + +import java.util.TreeMap; + +@AllArgsConstructor +public class MQDomainContextSender implements MQDomainMessageSender { + private final TreeMap senders; // + + @Override + public Mono send(String domain, Destination destination, MQMessageCreator messageCreator) { + return senders.get(domain).send(destination, messageCreator); + } + + @Override + public Mono send(String domain, MQMessageCreator messageCreator) { + return senders.get(domain).send(messageCreator); + } + + @Override + public MQMessageSender forDomain(String domain) { + return senders.get(domain); + } +} diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSender.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSender.java index 6d2f4b6..7c4d91e 100644 --- a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSender.java +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSender.java @@ -3,12 +3,11 @@ import co.com.bancolombia.commons.jms.api.MQMessageCreator; import co.com.bancolombia.commons.jms.api.MQMessageSender; import co.com.bancolombia.commons.jms.api.MQMessageSenderSync; +import jakarta.jms.Destination; import lombok.AllArgsConstructor; import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; -import jakarta.jms.Destination; - @AllArgsConstructor public class MQMultiContextSender implements MQMessageSender { private final MQMessageSenderSync senderSync; // MQMultiContextSenderSync diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderSync.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderSync.java index 3b88912..c341f91 100644 --- a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderSync.java +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderSync.java @@ -1,47 +1,30 @@ package co.com.bancolombia.commons.jms.internal.sender; -import co.com.bancolombia.commons.jms.api.MQDestinationProvider; import co.com.bancolombia.commons.jms.api.MQMessageCreator; import co.com.bancolombia.commons.jms.api.MQMessageSenderSync; -import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; -import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; - -import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; -import jakarta.jms.ConnectionFactory; +import co.com.bancolombia.commons.jms.internal.models.MQSenderConfig; import jakarta.jms.Destination; +import lombok.extern.log4j.Log4j2; + import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; +@Log4j2 public class MQMultiContextSenderSync implements MQMessageSenderSync { - private final ConnectionFactory connectionFactory; - private List adapterList; + private final List adapterList; private final int connections; - private final MQDestinationProvider provider; - private final MQProducerCustomizer customizer; - private final MQHealthListener healthListener; - private final RetryableConfig retryableConfig; - - public MQMultiContextSenderSync(ConnectionFactory connectionFactory, int connections, - MQDestinationProvider provider, MQProducerCustomizer customizer, - MQHealthListener healthListener, RetryableConfig retryableConfig) { - this.connectionFactory = connectionFactory; - this.connections = connections; - this.provider = provider; - this.customizer = customizer; - this.healthListener = healthListener; - this.retryableConfig = retryableConfig; - start(); - } - public void start() { - adapterList = IntStream.range(0, connections) + public MQMultiContextSenderSync(MQSenderConfig senderConfig) { + this.connections = senderConfig.getConcurrency(); + if (log.isInfoEnabled()) { + log.info("Generating {} senders", connections); + } + adapterList = IntStream.range(0, senderConfig.getConcurrency()) .mapToObj(idx -> MQContextSenderSync.builder() - .connectionFactory(connectionFactory) - .customizer(customizer) - .provider(provider) - .healthListener(healthListener) - .retryableConfig(retryableConfig) + .senderConfig(senderConfig) + .healthListener(senderConfig.getHealthListener()) + .retryableConfig(senderConfig.getRetryableConfig()) .build() .call()) .collect(Collectors.toList()); diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/MQMessageListenerUtils.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/MQMessageListenerUtils.java index 1c6d191..236a368 100644 --- a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/MQMessageListenerUtils.java +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/MQMessageListenerUtils.java @@ -6,12 +6,9 @@ import co.com.bancolombia.commons.jms.internal.listener.MQContextListener; import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; -import jakarta.jms.ConnectionFactory; -import jakarta.jms.MessageListener; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.log4j.Log4j2; -import org.apache.commons.lang3.StringUtils; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -21,11 +18,9 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class MQMessageListenerUtils { - public static void createListeners(ConnectionFactory cf, - MessageListener listener, + public static void createListeners(MQListenerConfig config, MQQueuesContainer container, MQBrokerUtils utils, - MQListenerConfig config, MQHealthListener healthListener, RetryableConfig retryableConfig) { if (log.isInfoEnabled()) { @@ -34,18 +29,15 @@ public static void createListeners(ConnectionFactory cf, ExecutorService service = Executors.newFixedThreadPool(config.getConcurrency()); IntStream.range(0, config.getConcurrency()) .mapToObj(number -> MQContextListener.builder() - .connectionFactory(cf) - .temporary(StringUtils.isNotBlank(config.getTempQueueAlias())) - .utils(utils) - .config(config) - .listener(listener) + .listenerConfig(config) .container(container) + .utils(utils) .healthListener(healthListener) .retryableConfig(retryableConfig) .build()) .forEach(service::submit); if (log.isInfoEnabled()) { - log.info("{} listeners created for {}", config.getConcurrency(), config.getQueue()); + log.info("{} listeners created for {}", config.getConcurrency(), config.getListeningQueue()); } } diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/MQQueueUtils.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/MQQueueUtils.java index e072970..e1d6c0d 100644 --- a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/MQQueueUtils.java +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/MQQueueUtils.java @@ -14,7 +14,7 @@ public class MQQueueUtils { public static Destination setupFixedQueue(JMSContext context, MQListenerConfig config) { - Queue queue = context.createQueue(config.getQueue()); + Queue queue = context.createQueue(config.getListeningQueue()); customize(queue, config); if (config.getQmSetter() != null) { config.getQmSetter().accept(context, queue); @@ -29,9 +29,9 @@ public static TemporaryQueue setupTemporaryQueue(JMSContext context, MQListenerC } private static void customize(T queue, MQListenerConfig config) { - if (config.getCustomizer() != null) { + if (config.getQueueCustomizer() != null) { try { - config.getCustomizer().customize(queue); + config.getQueueCustomizer().customize(queue); } catch (Exception ex) { log.warn("Error customizing queue", ex); } diff --git a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/ReactiveReplyRouter.java b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/ReactiveReplyRouter.java index 6b3e2f0..f30f8a2 100644 --- a/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/ReactiveReplyRouter.java +++ b/commons-jms-utils/src/main/java/co/com/bancolombia/commons/jms/utils/ReactiveReplyRouter.java @@ -13,6 +13,7 @@ public class ReactiveReplyRouter { private final ConcurrentHashMap> processors = new ConcurrentHashMap<>(); + public Mono wait(String messageId) { final Sinks.One processor = Sinks.one(); processors.put(messageId, processor); diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/MQContextListenerTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/MQContextListenerTest.java index 7b4cc21..ce48264 100644 --- a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/MQContextListenerTest.java +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/MQContextListenerTest.java @@ -42,9 +42,11 @@ class MQContextListenerTest { @BeforeEach void setup() { contextListener = MQContextListener.builder() - .config(MQListenerConfig.builder().queue("QUEUE.NAME").build()) - .listener(listener) - .connectionFactory(connectionFactory) + .listenerConfig(MQListenerConfig.builder() + .messageListener(listener) + .connectionFactory(connectionFactory) + .listeningQueue("QUEUE.NAME") + .build()) .container(new MQQueuesContainerImp()) .healthListener(healthListener) .utils(utils) diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/MQContextTemporaryListenerTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/MQContextTemporaryListenerTest.java index e0b0247..a30a138 100644 --- a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/MQContextTemporaryListenerTest.java +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/MQContextTemporaryListenerTest.java @@ -7,7 +7,6 @@ import jakarta.jms.JMSConsumer; import jakarta.jms.JMSContext; import jakarta.jms.JMSException; -import jakarta.jms.JMSRuntimeException; import jakarta.jms.MessageListener; import jakarta.jms.TemporaryQueue; import org.junit.jupiter.api.BeforeEach; @@ -16,7 +15,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static co.com.bancolombia.commons.jms.internal.models.MQListenerConfig.QueueType.TEMPORARY; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -49,12 +48,14 @@ void setup() throws JMSException { when(context.createConsumer(any())).thenReturn(consumer); when(tmpQueue.getQueueName()).thenReturn("AMQ.QUEUE"); contextTemporaryListener = MQContextListener.builder() - .listener(listener) - .temporary(true) - .connectionFactory(connectionFactory) + .listenerConfig(MQListenerConfig.builder() + .listeningQueue("alias") + .messageListener(listener) + .queueType(TEMPORARY) + .connectionFactory(connectionFactory) + .build()) .container(new MQQueuesContainerImp()) .healthListener(healthListener) - .config(MQListenerConfig.builder().build()) .build(); } diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerSyncTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerSyncTest.java index 7e52279..3259d14 100644 --- a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerSyncTest.java +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerSyncTest.java @@ -1,5 +1,6 @@ package co.com.bancolombia.commons.jms.internal.listener.selector; +import co.com.bancolombia.commons.jms.api.MQQueuesContainer; import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; import co.com.bancolombia.commons.jms.api.exceptions.ReceiveTimeoutException; import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.ContextPerMessageStrategy; @@ -52,14 +53,12 @@ class MQMultiContextMessageSelectorListenerSyncTest { private Destination destination; @Mock private SelectorModeProvider selectorModeProvider; + @Mock + private MQQueuesContainer container; private MQMultiContextMessageSelectorListenerSync listenerSync; - private final MQListenerConfig config = MQListenerConfig - .builder() - .concurrency(1) - .queue("QUEUE") - .build(); + private MQListenerConfig config; private final RetryableConfig retryableConfig = RetryableConfig .builder() .maxRetries(10) @@ -69,19 +68,25 @@ class MQMultiContextMessageSelectorListenerSyncTest { @BeforeEach void setup() { - when(connectionFactory.createContext()).thenReturn(context); - when(context.createQueue(anyString())).thenReturn(queue); when(selectorModeProvider.get(any(), any())) .thenReturn(SelectorModeProvider.defaultSelector().get(connectionFactory, context)); - listenerSync = new MQMultiContextMessageSelectorListenerSync(connectionFactory, config, healthListener, - retryableConfig, selectorModeProvider); + when(connectionFactory.createContext()).thenReturn(context); + when(context.createQueue(anyString())).thenReturn(queue); + config = MQListenerConfig + .builder() + .concurrency(1) + .connectionFactory(connectionFactory) + .listeningQueue("QUEUE") + .build(); + listenerSync = new MQMultiContextMessageSelectorListenerSync(config, healthListener, + retryableConfig, selectorModeProvider, container); } @Test void shouldGetMessageWithContextPerMessage() { - listenerSync = new MQMultiContextMessageSelectorListenerSync(connectionFactory, config, healthListener, - retryableConfig, (factory, ignored) -> new ContextPerMessageStrategy(factory)); // Arrange + listenerSync = new MQMultiContextMessageSelectorListenerSync(config, healthListener, + retryableConfig, (factory, ignored) -> new ContextPerMessageStrategy(factory), container); String messageID = UUID.randomUUID().toString(); when(context.createConsumer(any(Destination.class), anyString())).thenReturn(consumer); when(consumer.receive(DEFAULT_TIMEOUT)).thenReturn(message); @@ -92,11 +97,26 @@ void shouldGetMessageWithContextPerMessage() { verify(consumer, times(1)).receive(DEFAULT_TIMEOUT); } + @Test + void shouldGetMessageWithContextPerMessageWithErrorTimeout() { + // Arrange + listenerSync = new MQMultiContextMessageSelectorListenerSync(config, healthListener, + retryableConfig, (factory, ignored) -> new ContextPerMessageStrategy(factory), container); + String messageID = UUID.randomUUID().toString(); + when(context.createConsumer(any(Destination.class), anyString())).thenReturn(consumer); + when(consumer.receive(DEFAULT_TIMEOUT)).thenReturn(null); + // Assert + assertThrows(ReceiveTimeoutException.class, () -> { + // Act + listenerSync.getMessage(messageID); + }); + } + @Test void shouldGetMessage() { - listenerSync = new MQMultiContextMessageSelectorListenerSync(connectionFactory, config, healthListener, - retryableConfig, SelectorModeProvider.defaultSelector()); // Arrange + listenerSync = new MQMultiContextMessageSelectorListenerSync(config, healthListener, + retryableConfig, SelectorModeProvider.defaultSelector(), container); String messageID = UUID.randomUUID().toString(); when(context.createConsumer(any(Destination.class), anyString())).thenReturn(consumer); when(consumer.receive(DEFAULT_TIMEOUT)).thenReturn(message); @@ -146,6 +166,19 @@ void shouldGetMessageBySelectorWithTimeout() { verify(consumer, times(1)).receive(DEFAULT_TIMEOUT); } + @Test + void shouldGetMessageBySelectorWithTimeoutError() { + // Arrange + String messageID = UUID.randomUUID().toString(); + when(context.createConsumer(any(Destination.class), anyString())).thenReturn(consumer); + when(consumer.receive(DEFAULT_TIMEOUT)).thenReturn(null); + // Assert + assertThrows(ReceiveTimeoutException.class, () -> { + // Act + listenerSync.getMessageBySelector("JMSMessageID='" + messageID + "'", DEFAULT_TIMEOUT); + }); + } + @Test void shouldRetrySelectMessageById() { // Arrange diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerTest.java index cfc2097..b27f46a 100644 --- a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerTest.java +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/listener/selector/MQMultiContextMessageSelectorListenerTest.java @@ -2,6 +2,7 @@ import co.com.bancolombia.commons.jms.api.MQMessageSelectorListener; import co.com.bancolombia.commons.jms.api.MQMessageSelectorListenerSync; +import co.com.bancolombia.commons.jms.api.MQQueuesContainer; import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; import co.com.bancolombia.commons.jms.api.exceptions.ReceiveTimeoutException; import co.com.bancolombia.commons.jms.internal.listener.selector.strategy.SelectorModeProvider; @@ -49,6 +50,8 @@ class MQMultiContextMessageSelectorListenerTest { private TextMessage message; @Mock private MQHealthListener healthListener; + @Mock + private MQQueuesContainer container; private MQMessageSelectorListener listener; @@ -58,7 +61,8 @@ void setup() { when(context.createQueue(anyString())).thenReturn(queue); MQListenerConfig config = MQListenerConfig.builder() .concurrency(1) - .queue("QUEUE") + .connectionFactory(connectionFactory) + .listeningQueue("QUEUE") .build(); RetryableConfig retryableConfig = RetryableConfig .builder() @@ -67,8 +71,8 @@ void setup() { .multiplier(1.5) .build(); MQMessageSelectorListenerSync listenerSync = - new MQMultiContextMessageSelectorListenerSync(connectionFactory, config, healthListener, - retryableConfig, SelectorModeProvider.defaultSelector()); + new MQMultiContextMessageSelectorListenerSync(config, healthListener, + retryableConfig, SelectorModeProvider.defaultSelector(), container); listener = new MQMultiContextMessageSelectorListener(listenerSync, Executors.newCachedThreadPool(), new ReactiveReplyRouter<>()); } diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/reconnect/AbstractJMSReconnectableTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/reconnect/AbstractJMSReconnectableTest.java index 91ce07b..69272f6 100644 --- a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/reconnect/AbstractJMSReconnectableTest.java +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/reconnect/AbstractJMSReconnectableTest.java @@ -1,6 +1,7 @@ package co.com.bancolombia.commons.jms.internal.reconnect; import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import jakarta.jms.JMSException; import lombok.experimental.SuperBuilder; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -8,8 +9,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import jakarta.jms.JMSException; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.times; diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderSyncTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderSyncTest.java index 472cd3d..e49e510 100644 --- a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderSyncTest.java +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderSyncTest.java @@ -2,20 +2,29 @@ import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; +import co.com.bancolombia.commons.jms.internal.models.MQSenderConfig; import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; +import jakarta.jms.ConnectionFactory; +import jakarta.jms.JMSContext; +import jakarta.jms.JMSException; +import jakarta.jms.JMSProducer; +import jakarta.jms.JMSRuntimeException; +import jakarta.jms.Queue; +import jakarta.jms.TextMessage; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import jakarta.jms.*; import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -48,8 +57,15 @@ void setup() { .initialRetryIntervalMillis(1000) .multiplier(1.5) .build(); - senderSync = new MQMultiContextSenderSync(connectionFactory, 2, - ctx -> ctx.createQueue("QUEUE.NAME"), customizer, healthListener, retryableConfig); + MQSenderConfig config = MQSenderConfig.builder() + .producerCustomizer(customizer) + .healthListener(healthListener) + .retryableConfig(retryableConfig) + .destinationProvider(ctx -> ctx.createQueue("QUEUE.NAME")) + .connectionFactory(connectionFactory) + .concurrency(2) + .build(); + senderSync = new MQMultiContextSenderSync(config); } @Test diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderTest.java index ffac5e9..3668349 100644 --- a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderTest.java +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/internal/sender/MQMultiContextSenderTest.java @@ -1,5 +1,7 @@ package co.com.bancolombia.commons.jms.internal.sender; +import jakarta.jms.Destination; +import jakarta.jms.JMSContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -8,8 +10,6 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import jakarta.jms.Destination; -import jakarta.jms.JMSContext; import java.util.UUID; import static org.mockito.ArgumentMatchers.any; diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQMessageListenerUtilsTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQMessageListenerUtilsTest.java index c9648ef..b885ae6 100644 --- a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQMessageListenerUtilsTest.java +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQMessageListenerUtilsTest.java @@ -5,23 +5,18 @@ import co.com.bancolombia.commons.jms.api.exceptions.MQHealthListener; import co.com.bancolombia.commons.jms.internal.models.MQListenerConfig; import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; -import jakarta.jms.JMSContext; +import jakarta.jms.ConnectionFactory; +import jakarta.jms.JMSException; +import jakarta.jms.MessageListener; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import jakarta.jms.Connection; -import jakarta.jms.ConnectionFactory; -import jakarta.jms.JMSException; -import jakarta.jms.MessageListener; -import jakarta.jms.Session; -import jakarta.jms.TemporaryQueue; - +import static co.com.bancolombia.commons.jms.internal.models.MQListenerConfig.QueueType.TEMPORARY; import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.times; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class MQMessageListenerUtilsTest { @@ -34,18 +29,16 @@ class MQMessageListenerUtilsTest { @Mock private MQBrokerUtils utils; @Mock - private JMSContext context; - @Mock - private TemporaryQueue queue; - @Mock private MQHealthListener healthListener; @Test void shouldCreateFixedQueueListeners() { // Arrange MQListenerConfig config = MQListenerConfig.builder() - .queue("QUEUE.NAME") + .listeningQueue("QUEUE.NAME") .concurrency(5) + .messageListener(listener) + .connectionFactory(connectionFactory) .build(); RetryableConfig retryableConfig = RetryableConfig .builder() @@ -54,27 +47,27 @@ void shouldCreateFixedQueueListeners() { .multiplier(1.5) .build(); // Act - MQMessageListenerUtils.createListeners(connectionFactory, listener, container, utils, config, healthListener, retryableConfig); + MQMessageListenerUtils.createListeners(config, container, utils, healthListener, retryableConfig); } @Test void shouldCreateTemporaryQueueListeners() throws JMSException { // Arrange - MQListenerConfig config = MQListenerConfig.builder() - .tempQueueAlias("alias") + MQListenerConfig config = spy(MQListenerConfig.builder() + .listeningQueue("alias") + .connectionFactory(connectionFactory) + .queueType(TEMPORARY) .concurrency(5) - .build(); + .build()); RetryableConfig retryableConfig = RetryableConfig .builder() .maxRetries(10) .initialRetryIntervalMillis(1000) .multiplier(1.5) .build(); - when(connectionFactory.createContext()).thenReturn(context); - when(context.createTemporaryQueue()).thenReturn(queue); // Act - MQMessageListenerUtils.createListeners(connectionFactory, listener, container, utils, config, healthListener, retryableConfig); + MQMessageListenerUtils.createListeners(config, container, utils, healthListener, retryableConfig); // Assert - verify(connectionFactory, atLeastOnce()).createContext(); + verify(config, atLeastOnce()).getConcurrency(); } } diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQQueueUtilsTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQQueueUtilsTest.java index 4437aba..2bffafb 100644 --- a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQQueueUtilsTest.java +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQQueueUtilsTest.java @@ -38,8 +38,8 @@ class MQQueueUtilsTest { @BeforeEach void setup() { config = MQListenerConfig.builder() - .queue("QUEUE.NAME") - .customizer(customizer) + .listeningQueue("QUEUE.NAME") + .queueCustomizer(customizer) .build(); } @@ -49,8 +49,8 @@ void shouldCreateFixedQueue() { when(context.createQueue(anyString())).thenReturn(queue); // Act Destination destination = MQQueueUtils.setupFixedQueue(context, MQListenerConfig.builder() - .queue("QUEUE.NAME") - .customizer(null) + .listeningQueue("QUEUE.NAME") + .queueCustomizer(null) .build()); // Assert verify(context, times(1)).createQueue(anyString()); @@ -63,8 +63,8 @@ void shouldCustomizeQueue() throws JMSException { when(context.createQueue(anyString())).thenReturn(queue); // Act Destination destination = MQQueueUtils.setupFixedQueue(context, MQListenerConfig.builder() - .queue("QUEUE.NAME") - .customizer(Queue::getQueueName) + .listeningQueue("QUEUE.NAME") + .queueCustomizer(Queue::getQueueName) .build()); // Assert verify(context, times(1)).createQueue(anyString()); diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQQueuesContainerImpTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQQueuesContainerImpTest.java index 3444ab1..6337f8d 100644 --- a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQQueuesContainerImpTest.java +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/MQQueuesContainerImpTest.java @@ -1,20 +1,31 @@ package co.com.bancolombia.commons.jms.utils; import co.com.bancolombia.commons.jms.api.MQQueuesContainer; +import jakarta.jms.Queue; +import jakarta.jms.TemporaryQueue; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import jakarta.jms.Queue; -import jakarta.jms.TemporaryQueue; - import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(MockitoExtension.class) class MQTemporaryQueuesContainerImpTest { @Mock private TemporaryQueue queue; + private MQQueuesContainer container; + + @BeforeEach + void setup(){ + container = new MQQueuesContainerImp(); + } + + @Test + void shouldBePrintable(){ + assertEquals("MQQueuesContainerImp{tempQueues={}, tempQueueGroups={}}", container.toString()); + } @Test void shouldSaveAndGet() { @@ -33,11 +44,16 @@ void shouldSaveAndGet() { class MQQueuesContainerImpTest { @Mock private Queue queue; + private MQQueuesContainer container; + + @BeforeEach + void setup(){ + container = new MQQueuesContainerImp(); + } @Test void shouldSaveAndGet() { // Arrange - MQQueuesContainer container = new MQQueuesContainerImp(); String alias = "key"; // Act container.registerQueue(alias, queue); @@ -49,7 +65,6 @@ void shouldSaveAndGet() { @Test void shouldSaveAndGetWhenGroup() { // Arrange - MQQueuesContainer container = new MQQueuesContainerImp(); String alias = "key"; // Act container.registerToQueueGroup(alias, queue); diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/ReactiveReplyRouterTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/ReactiveReplyRouterTest.java index f06be5b..cffa684 100644 --- a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/ReactiveReplyRouterTest.java +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/ReactiveReplyRouterTest.java @@ -20,6 +20,12 @@ void shouldReply() { StepVerifier.create(flow).expectNext("result").verifyComplete(); } + @Test + void shouldFailNotFoundWhenError() { + router.error(null, new Exception("Some Error")); + assertThrows(RelatedMessageNotFoundException.class, () -> router.error("1234", new Exception("Some Error"))); + } + @Test void shouldFailNotFound() { assertThrows(RelatedMessageNotFoundException.class, () -> router.reply("1234", "result")); diff --git a/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/RetryableTaskTest.java b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/RetryableTaskTest.java new file mode 100644 index 0000000..0cd5598 --- /dev/null +++ b/commons-jms-utils/src/test/java/co/com/bancolombia/commons/jms/utils/RetryableTaskTest.java @@ -0,0 +1,34 @@ +package co.com.bancolombia.commons.jms.utils; + +import co.com.bancolombia.commons.jms.internal.models.RetryableConfig; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class RetryableTaskTest { + @Mock + private Runnable runnable; + + @Test + void shouldRetry() { + // Arrange + doThrow(new RuntimeException("Error")).when(runnable).run(); + RetryableConfig config = RetryableConfig.builder() + .initialRetryIntervalMillis(10) + .maxRetries(3) + .build(); + // Assert + Assertions.assertThrows(RuntimeException.class, () -> { + // Act + RetryableTask.runWithRetries("sample", config, runnable); + }); + verify(runnable, times(3)).run(); + } +} diff --git a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/app/MainApplication.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/app/MainApplication.java similarity index 86% rename from examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/app/MainApplication.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/app/MainApplication.java index 3af6e2e..69adcfa 100644 --- a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/app/MainApplication.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/app/MainApplication.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.selector.app; +package co.com.bancolombia.sample.noreactive.app; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/app/config/Config.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/app/config/Config.java similarity index 83% rename from examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/app/config/Config.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/app/config/Config.java index 287f558..a434864 100644 --- a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/app/config/Config.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/app/config/Config.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.selector.app.config; +package co.com.bancolombia.sample.noreactive.app.config; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/app/config/UseCasesConfig.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/app/config/UseCasesConfig.java similarity index 88% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/app/config/UseCasesConfig.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/app/config/UseCasesConfig.java index cf8b4e7..d43edea 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/app/config/UseCasesConfig.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/app/config/UseCasesConfig.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.noreactive.app.config; +package co.com.bancolombia.sample.noreactive.app.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; diff --git a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/exceptions/ParseMessageException.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/exceptions/ParseMessageException.java similarity index 68% rename from examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/exceptions/ParseMessageException.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/exceptions/ParseMessageException.java index 56d603d..c4f5290 100644 --- a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/exceptions/ParseMessageException.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/exceptions/ParseMessageException.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.selector.domain.exceptions; +package co.com.bancolombia.sample.noreactive.domain.exceptions; public class ParseMessageException extends RuntimeException { public ParseMessageException(Throwable cause) { diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/exceptions/RelatedMessageNotFoundException.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/exceptions/RelatedMessageNotFoundException.java similarity index 52% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/exceptions/RelatedMessageNotFoundException.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/exceptions/RelatedMessageNotFoundException.java index d452869..27ef6f5 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/exceptions/RelatedMessageNotFoundException.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/exceptions/RelatedMessageNotFoundException.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.noreactive.domain.exceptions; +package co.com.bancolombia.sample.noreactive.domain.exceptions; public class RelatedMessageNotFoundException extends RuntimeException { } diff --git a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/model/Request.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/model/Request.java similarity index 79% rename from examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/model/Request.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/model/Request.java index c61cab6..498af2d 100644 --- a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/model/Request.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/model/Request.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.selector.domain.model; +package co.com.bancolombia.sample.noreactive.domain.model; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/model/RequestGateway.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/model/RequestGateway.java similarity index 52% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/model/RequestGateway.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/model/RequestGateway.java index f5cee48..2dea39a 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/model/RequestGateway.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/model/RequestGateway.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.noreactive.domain.model; +package co.com.bancolombia.sample.noreactive.domain.model; public interface RequestGateway { String send(Request request); diff --git a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/model/Result.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/model/Result.java similarity index 80% rename from examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/model/Result.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/model/Result.java index 5881e9e..7476a36 100644 --- a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/model/Result.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/model/Result.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.selector.domain.model; +package co.com.bancolombia.sample.noreactive.domain.model; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/usecase/ReplyRouterUseCase.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/usecase/ReplyRouterUseCase.java similarity index 82% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/usecase/ReplyRouterUseCase.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/usecase/ReplyRouterUseCase.java index 8b5660e..fbacc16 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/usecase/ReplyRouterUseCase.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/usecase/ReplyRouterUseCase.java @@ -1,7 +1,7 @@ -package co.com.bancolombia.jms.sample.noreactive.domain.usecase; +package co.com.bancolombia.sample.noreactive.domain.usecase; -import co.com.bancolombia.jms.sample.noreactive.domain.exceptions.RelatedMessageNotFoundException; -import co.com.bancolombia.jms.sample.noreactive.domain.model.Result; +import co.com.bancolombia.sample.noreactive.domain.exceptions.RelatedMessageNotFoundException; +import co.com.bancolombia.sample.noreactive.domain.model.Result; import lombok.extern.log4j.Log4j2; import java.util.concurrent.CompletableFuture; diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/usecase/SampleUseCase.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/usecase/SampleUseCase.java similarity index 69% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/usecase/SampleUseCase.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/usecase/SampleUseCase.java index 72852e8..40a3d9b 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/usecase/SampleUseCase.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/domain/usecase/SampleUseCase.java @@ -1,8 +1,8 @@ -package co.com.bancolombia.jms.sample.noreactive.domain.usecase; +package co.com.bancolombia.sample.noreactive.domain.usecase; -import co.com.bancolombia.jms.sample.noreactive.domain.model.Request; -import co.com.bancolombia.jms.sample.noreactive.domain.model.RequestGateway; -import co.com.bancolombia.jms.sample.noreactive.domain.model.Result; +import co.com.bancolombia.sample.noreactive.domain.model.RequestGateway; +import co.com.bancolombia.sample.noreactive.domain.model.Request; +import co.com.bancolombia.sample.noreactive.domain.model.Result; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import lombok.extern.log4j.Log4j2; diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/drivenadapters/MyMQSender.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/drivenadapters/MyMQSender.java similarity index 67% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/drivenadapters/MyMQSender.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/drivenadapters/MyMQSender.java index c6464ae..2dc1f1c 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/drivenadapters/MyMQSender.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/drivenadapters/MyMQSender.java @@ -1,10 +1,10 @@ -package co.com.bancolombia.jms.sample.noreactive.drivenadapters; +package co.com.bancolombia.sample.noreactive.drivenadapters; import co.com.bancolombia.commons.jms.api.MQMessageSenderSync; -import co.com.bancolombia.commons.jms.mq.EnableMQMessageSender; -import co.com.bancolombia.jms.sample.noreactive.domain.exceptions.ParseMessageException; -import co.com.bancolombia.jms.sample.noreactive.domain.model.Request; -import co.com.bancolombia.jms.sample.noreactive.domain.model.RequestGateway; +import co.com.bancolombia.commons.jms.mq.EnableMQGateway; +import co.com.bancolombia.sample.noreactive.domain.exceptions.ParseMessageException; +import co.com.bancolombia.sample.noreactive.domain.model.Request; +import co.com.bancolombia.sample.noreactive.domain.model.RequestGateway; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; @@ -12,7 +12,7 @@ @Component @AllArgsConstructor -@EnableMQMessageSender +@EnableMQGateway public class MyMQSender implements RequestGateway { private final MQMessageSenderSync sender; private final ObjectMapper mapper; diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/entrypoints/MyMQListener.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/entrypoints/MyMQListener.java similarity index 80% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/entrypoints/MyMQListener.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/entrypoints/MyMQListener.java index b8b29a3..8bb4ac1 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/entrypoints/MyMQListener.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/entrypoints/MyMQListener.java @@ -1,18 +1,18 @@ -package co.com.bancolombia.jms.sample.noreactive.entrypoints; +package co.com.bancolombia.sample.noreactive.entrypoints; import co.com.bancolombia.commons.jms.mq.MQListener; -import co.com.bancolombia.jms.sample.noreactive.domain.model.Request; -import co.com.bancolombia.jms.sample.noreactive.domain.model.Result; -import co.com.bancolombia.jms.sample.noreactive.domain.usecase.ReplyRouterUseCase; +import co.com.bancolombia.sample.noreactive.domain.usecase.ReplyRouterUseCase; +import co.com.bancolombia.sample.noreactive.domain.model.Request; +import co.com.bancolombia.sample.noreactive.domain.model.Result; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.jms.JMSException; +import jakarta.jms.Message; +import jakarta.jms.TextMessage; import lombok.AllArgsConstructor; import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Component; -import jakarta.jms.JMSException; -import jakarta.jms.Message; -import jakarta.jms.TextMessage; import java.util.Date; @Log4j2 diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/entrypoints/Rest.java b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/entrypoints/Rest.java similarity index 66% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/entrypoints/Rest.java rename to examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/entrypoints/Rest.java index 7da6a64..5b02416 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/entrypoints/Rest.java +++ b/examples/mq-mvc-app/src/main/java/co/com/bancolombia/sample/noreactive/entrypoints/Rest.java @@ -1,7 +1,7 @@ -package co.com.bancolombia.jms.sample.noreactive.entrypoints; +package co.com.bancolombia.sample.noreactive.entrypoints; -import co.com.bancolombia.jms.sample.noreactive.domain.model.Result; -import co.com.bancolombia.jms.sample.noreactive.domain.usecase.SampleUseCase; +import co.com.bancolombia.sample.noreactive.domain.usecase.SampleUseCase; +import co.com.bancolombia.sample.noreactive.domain.model.Result; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/examples/mq-mvc-app/src/main/resources/application.yaml b/examples/mq-mvc-app/src/main/resources/application.yaml index d03959c..7106d64 100644 --- a/examples/mq-mvc-app/src/main/resources/application.yaml +++ b/examples/mq-mvc-app/src/main/resources/application.yaml @@ -10,7 +10,6 @@ commons: producer-ttl: 60 input-concurrency: 2 input-queue: "DEV.QUEUE.1" - input-queue-alias: "" ibm: mq: channel: "DEV.APP.SVRCONN" diff --git a/examples/mq-reactive-replier/README.md b/examples/mq-reactive-replier/README.md index bbf1b48..eb7bb69 100644 --- a/examples/mq-reactive-replier/README.md +++ b/examples/mq-reactive-replier/README.md @@ -6,6 +6,7 @@ You can do it with docker, please refer to [docker hub](https://hub.docker.com/r ```shell docker run -e LICENSE=accept -e MQ_QMGR_NAME=QM1 -p 1414:1414 -p 9443:9443 -d --name ibmmq -e MQ_APP_PASSWORD=passw0rd ibmcom/mq +docker run -e LICENSE=accept -e MQ_QMGR_NAME=QM2 -p 1415:1414 -p 9444:9443 -d --name ibmmq2 -e MQ_APP_PASSWORD=passw0rd ibmcom/mq ``` When MQ Server is running, run diff --git a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/app/config/Config.java b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/app/config/Config.java deleted file mode 100644 index aadff52..0000000 --- a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/app/config/Config.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.com.bancolombia.jms.replier.app.config; - -import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import jakarta.jms.DeliveryMode; - -@Configuration -public class Config { - - @Bean - public ObjectMapper objectMapper() { - return new ObjectMapper(); - } - - - /** - * When replying to a temporary queue - * - * @return MQProducerCustomizer - */ - @Bean - public MQProducerCustomizer producerCustomizer() { - return producer -> producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); - } -} diff --git a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/entrypoints/MyMQListener.java b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/entrypoints/MyMQListener.java deleted file mode 100644 index d623307..0000000 --- a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/entrypoints/MyMQListener.java +++ /dev/null @@ -1,36 +0,0 @@ -package co.com.bancolombia.jms.replier.entrypoints; - -import co.com.bancolombia.commons.jms.api.MQMessageSender; -import co.com.bancolombia.commons.jms.mq.EnableMQMessageSender; -import co.com.bancolombia.commons.jms.mq.MQListener; -import lombok.AllArgsConstructor; -import lombok.extern.log4j.Log4j2; -import org.springframework.stereotype.Component; -import reactor.core.publisher.Mono; - -import jakarta.jms.JMSException; -import jakarta.jms.Message; -import jakarta.jms.TextMessage; -import java.time.Duration; - -@Log4j2 -@Component -@AllArgsConstructor -@EnableMQMessageSender -public class MyMQListener { - private final MQMessageSender sender; - - @MQListener - public Mono process(Message message) throws JMSException { - log.info("Received and processing"); - TextMessage textMessage = (TextMessage) message; - String id = message.getJMSMessageID(); - log.info("Received with id: {}", id); - return sender.send(textMessage.getJMSReplyTo(), context -> { - TextMessage response = context.createTextMessage(textMessage.getText() + " replied"); - response.setJMSCorrelationID(textMessage.getJMSMessageID()); - return response; - }).then() - .delaySubscription(Duration.ofMillis(100)); // Simulates some latency - } -} diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/app/MainApplication.java b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/app/MainApplication.java similarity index 87% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/app/MainApplication.java rename to examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/app/MainApplication.java index 7ab0f29..0f77252 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/app/MainApplication.java +++ b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/app/MainApplication.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.app; +package co.com.bancolombia.sample.replier.app; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/app/config/Config.java b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/app/config/Config.java new file mode 100644 index 0000000..310adf1 --- /dev/null +++ b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/app/config/Config.java @@ -0,0 +1,74 @@ +package co.com.bancolombia.sample.replier.app.config; + +import co.com.bancolombia.commons.jms.api.MQProducerCustomizer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ibm.mq.jakarta.jms.MQConnectionFactory; +import com.ibm.mq.spring.boot.MQConfigurationProperties; +import com.ibm.mq.spring.boot.MQConnectionFactoryCustomizer; +import com.ibm.mq.spring.boot.MQConnectionFactoryFactory; +import jakarta.jms.ConnectionFactory; +import jakarta.jms.DeliveryMode; +import lombok.SneakyThrows; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.jms.JmsProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.jms.connection.CachingConnectionFactory; + +import java.util.List; + +@Configuration +@EnableConfigurationProperties({MQConfigurationProperties.class, JmsProperties.class}) +public class Config { + + @Bean + public ObjectMapper objectMapper() { + return new ObjectMapper(); + } + + + /** + * When replying to a temporary queue + * + * @return MQProducerCustomizer + */ + @Bean + public MQProducerCustomizer producerCustomizer() { + return producer -> producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + } + + @Bean + @Primary + @SneakyThrows + public ConnectionFactory cachingJmsConnectionFactory(MQConfigurationProperties properties, ObjectProvider> factoryCustomizers, JmsProperties jmsProperties) { + JmsProperties.Cache cacheProperties = jmsProperties.getCache(); + properties.setQueueManager("QM1"); + properties.setConnName("localhost(1414)"); + MQConnectionFactory wrappedConnectionFactory = createConnectionFactory(properties, factoryCustomizers); + CachingConnectionFactory connectionFactory = new CachingConnectionFactory(wrappedConnectionFactory); + connectionFactory.setCacheConsumers(cacheProperties.isConsumers()); + connectionFactory.setCacheProducers(cacheProperties.isProducers()); + connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize()); + return connectionFactory; + } + + @Bean + @SneakyThrows + public ConnectionFactory domainB(MQConfigurationProperties properties, ObjectProvider> factoryCustomizers, JmsProperties jmsProperties) { + JmsProperties.Cache cacheProperties = jmsProperties.getCache(); + properties.setQueueManager("QM2"); + properties.setConnName("localhost(1415)"); + MQConnectionFactory wrappedConnectionFactory = createConnectionFactory(properties, factoryCustomizers); + CachingConnectionFactory connectionFactory = new CachingConnectionFactory(wrappedConnectionFactory); + connectionFactory.setCacheConsumers(cacheProperties.isConsumers()); + connectionFactory.setCacheProducers(cacheProperties.isProducers()); + connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize()); + return connectionFactory; + } + + private static MQConnectionFactory createConnectionFactory(MQConfigurationProperties properties, ObjectProvider> factoryCustomizers) { + return (new MQConnectionFactoryFactory(properties, factoryCustomizers.getIfAvailable())).createConnectionFactory(MQConnectionFactory.class); + } +} diff --git a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/app/config/UseCasesConfig.java b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/app/config/UseCasesConfig.java similarity index 89% rename from examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/app/config/UseCasesConfig.java rename to examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/app/config/UseCasesConfig.java index 51ece68..d7b547f 100644 --- a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/app/config/UseCasesConfig.java +++ b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/app/config/UseCasesConfig.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.replier.app.config; +package co.com.bancolombia.sample.replier.app.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; diff --git a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/domain/model/Request.java b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/domain/model/Request.java similarity index 81% rename from examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/domain/model/Request.java rename to examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/domain/model/Request.java index fdb5661..cd26bb6 100644 --- a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/domain/model/Request.java +++ b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/domain/model/Request.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.replier.domain.model; +package co.com.bancolombia.sample.replier.domain.model; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/domain/model/Result.java b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/domain/model/Result.java similarity index 81% rename from examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/domain/model/Result.java rename to examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/domain/model/Result.java index 10244c6..6e5a0a5 100644 --- a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/domain/model/Result.java +++ b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/domain/model/Result.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.replier.domain.model; +package co.com.bancolombia.sample.replier.domain.model; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/drivenadapters/XDomainSender.java b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/drivenadapters/XDomainSender.java new file mode 100644 index 0000000..e6785b3 --- /dev/null +++ b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/drivenadapters/XDomainSender.java @@ -0,0 +1,8 @@ +package co.com.bancolombia.sample.replier.drivenadapters; + +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.mq.MQSender; + +@MQSender(connectionFactory = "domainB") +public interface XDomainSender extends MQMessageSender { +} diff --git a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/entrypoints/MyMQListener.java b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/entrypoints/MyMQListener.java new file mode 100644 index 0000000..d0debef --- /dev/null +++ b/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/sample/replier/entrypoints/MyMQListener.java @@ -0,0 +1,52 @@ +package co.com.bancolombia.sample.replier.entrypoints; + +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.mq.EnableMQGateway; +import co.com.bancolombia.commons.jms.mq.MQListener; +import co.com.bancolombia.sample.replier.drivenadapters.XDomainSender; +import jakarta.jms.JMSException; +import jakarta.jms.Message; +import jakarta.jms.TextMessage; +import lombok.AllArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.time.Duration; + +@Log4j2 +@Component +@AllArgsConstructor +@EnableMQGateway(scanBasePackages = "co.com.bancolombia") +public class MyMQListener { + private final MQMessageSender sender; + private final XDomainSender sender2; + + @MQListener + public Mono process(Message message) throws JMSException { + log.info("Received and processing from default domain"); + TextMessage textMessage = (TextMessage) message; + String id = message.getJMSMessageID(); + log.info("Received with id: {}", id); + return sender.send(textMessage.getJMSReplyTo(), context -> { + TextMessage response = context.createTextMessage(textMessage.getText() + " replied default domain"); + response.setJMSCorrelationID(textMessage.getJMSMessageID()); + return response; + }).then() + .delaySubscription(Duration.ofMillis(100)); // Simulates some latency + } + + @MQListener(connectionFactory = "domainB") + public Mono processFromDomainB(Message message) throws JMSException { + log.info("Received and processing from domainB"); + TextMessage textMessage = (TextMessage) message; + String id = message.getJMSMessageID(); + log.info("Received with id: {}", id); + return sender2.send(textMessage.getJMSReplyTo(), context -> { + TextMessage response = context.createTextMessage(textMessage.getText() + " replied domainB"); + response.setJMSCorrelationID(textMessage.getJMSMessageID()); + return response; + }).then() + .delaySubscription(Duration.ofMillis(100)); // Simulates some latency + } +} diff --git a/examples/mq-reactive-replier/src/main/resources/application.yaml b/examples/mq-reactive-replier/src/main/resources/application.yaml index bf931c7..be09d60 100644 --- a/examples/mq-reactive-replier/src/main/resources/application.yaml +++ b/examples/mq-reactive-replier/src/main/resources/application.yaml @@ -2,7 +2,7 @@ server: port: 8080 logging: level: - root: WARN + root: INFO spring: application: name: "mq-reactive-replier" @@ -14,7 +14,6 @@ commons: reactive: true input-concurrency: 5 input-queue: "DEV.QUEUE.1" - input-queue-alias: "" ibm: mq: channel: "DEV.APP.SVRCONN" diff --git a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/app/MainApplication.java b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/app/MainApplication.java similarity index 87% rename from examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/app/MainApplication.java rename to examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/app/MainApplication.java index faf0a3e..8c9fb8c 100644 --- a/examples/mq-reactive-replier/src/main/java/co/com/bancolombia/jms/replier/app/MainApplication.java +++ b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/app/MainApplication.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.replier.app; +package co.com.bancolombia.sample.selector.app; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/app/config/Config.java b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/app/config/Config.java similarity index 83% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/app/config/Config.java rename to examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/app/config/Config.java index d8d7608..4851b97 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/app/config/Config.java +++ b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/app/config/Config.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.noreactive.app.config; +package co.com.bancolombia.sample.selector.app.config; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; diff --git a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/app/config/UseCasesConfig.java b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/app/config/UseCasesConfig.java similarity index 88% rename from examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/app/config/UseCasesConfig.java rename to examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/app/config/UseCasesConfig.java index a97c2a6..13b6e9e 100644 --- a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/app/config/UseCasesConfig.java +++ b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/app/config/UseCasesConfig.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.selector.app.config; +package co.com.bancolombia.sample.selector.app.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/exceptions/ParseMessageException.java b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/exceptions/ParseMessageException.java similarity index 68% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/exceptions/ParseMessageException.java rename to examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/exceptions/ParseMessageException.java index 930afdb..8a6753b 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/exceptions/ParseMessageException.java +++ b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/exceptions/ParseMessageException.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.noreactive.domain.exceptions; +package co.com.bancolombia.sample.selector.domain.exceptions; public class ParseMessageException extends RuntimeException { public ParseMessageException(Throwable cause) { diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/model/Request.java b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/model/Request.java similarity index 79% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/model/Request.java rename to examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/model/Request.java index 31740d5..482bf42 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/model/Request.java +++ b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/model/Request.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.noreactive.domain.model; +package co.com.bancolombia.sample.selector.domain.model; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/model/RequestGateway.java b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/model/RequestGateway.java similarity index 73% rename from examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/model/RequestGateway.java rename to examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/model/RequestGateway.java index 5432ff6..1874ce0 100644 --- a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/model/RequestGateway.java +++ b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/model/RequestGateway.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.selector.domain.model; +package co.com.bancolombia.sample.selector.domain.model; import reactor.core.publisher.Mono; diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/model/Result.java b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/model/Result.java similarity index 79% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/model/Result.java rename to examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/model/Result.java index af0335c..52dc6f9 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/domain/model/Result.java +++ b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/model/Result.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.noreactive.domain.model; +package co.com.bancolombia.sample.selector.domain.model; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/usecase/SampleUseCase.java b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/usecase/SampleUseCase.java similarity index 69% rename from examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/usecase/SampleUseCase.java rename to examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/usecase/SampleUseCase.java index ffda555..0fdfae8 100644 --- a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/domain/usecase/SampleUseCase.java +++ b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/domain/usecase/SampleUseCase.java @@ -1,8 +1,8 @@ -package co.com.bancolombia.jms.sample.selector.domain.usecase; +package co.com.bancolombia.sample.selector.domain.usecase; -import co.com.bancolombia.jms.sample.selector.domain.model.Request; -import co.com.bancolombia.jms.sample.selector.domain.model.RequestGateway; -import co.com.bancolombia.jms.sample.selector.domain.model.Result; +import co.com.bancolombia.sample.selector.domain.model.Request; +import co.com.bancolombia.sample.selector.domain.model.RequestGateway; +import co.com.bancolombia.sample.selector.domain.model.Result; import lombok.AllArgsConstructor; import lombok.extern.log4j.Log4j2; import reactor.core.publisher.Mono; diff --git a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/drivenadapters/MyMQSender.java b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/drivenadapters/MyMQSender.java similarity index 79% rename from examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/drivenadapters/MyMQSender.java rename to examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/drivenadapters/MyMQSender.java index 73c6e2e..352cf42 100644 --- a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/drivenadapters/MyMQSender.java +++ b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/drivenadapters/MyMQSender.java @@ -1,14 +1,13 @@ -package co.com.bancolombia.jms.sample.selector.drivenadapters; +package co.com.bancolombia.sample.selector.drivenadapters; import co.com.bancolombia.commons.jms.api.MQMessageSelectorListener; import co.com.bancolombia.commons.jms.api.MQMessageSender; import co.com.bancolombia.commons.jms.api.MQQueuesContainer; -import co.com.bancolombia.commons.jms.mq.EnableMQMessageSender; -import co.com.bancolombia.commons.jms.mq.EnableMQSelectorMessageListener; -import co.com.bancolombia.jms.sample.selector.domain.exceptions.ParseMessageException; -import co.com.bancolombia.jms.sample.selector.domain.model.Request; -import co.com.bancolombia.jms.sample.selector.domain.model.RequestGateway; -import co.com.bancolombia.jms.sample.selector.domain.model.Result; +import co.com.bancolombia.commons.jms.mq.EnableMQGateway; +import co.com.bancolombia.sample.selector.domain.exceptions.ParseMessageException; +import co.com.bancolombia.sample.selector.domain.model.Request; +import co.com.bancolombia.sample.selector.domain.model.RequestGateway; +import co.com.bancolombia.sample.selector.domain.model.Result; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.jms.Message; @@ -24,8 +23,7 @@ @Component @Log4j2 @AllArgsConstructor -@EnableMQMessageSender -@EnableMQSelectorMessageListener +@EnableMQGateway public class MyMQSender implements RequestGateway { private final MQMessageSender sender; private final MQMessageSelectorListener listener; diff --git a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/entrypoints/Rest.java b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/entrypoints/Rest.java similarity index 84% rename from examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/entrypoints/Rest.java rename to examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/entrypoints/Rest.java index aa312ef..06e2c25 100644 --- a/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/jms/sample/selector/entrypoints/Rest.java +++ b/examples/mq-reactive-selector/src/main/java/co/com/bancolombia/sample/selector/entrypoints/Rest.java @@ -1,7 +1,7 @@ -package co.com.bancolombia.jms.sample.selector.entrypoints; +package co.com.bancolombia.sample.selector.entrypoints; -import co.com.bancolombia.jms.sample.selector.domain.model.Result; -import co.com.bancolombia.jms.sample.selector.domain.usecase.SampleUseCase; +import co.com.bancolombia.sample.selector.domain.model.Result; +import co.com.bancolombia.sample.selector.domain.usecase.SampleUseCase; import lombok.AllArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/examples/mq-reactive-selector/src/main/resources/application.yaml b/examples/mq-reactive-selector/src/main/resources/application.yaml index 8e68c8a..a624429 100644 --- a/examples/mq-reactive-selector/src/main/resources/application.yaml +++ b/examples/mq-reactive-selector/src/main/resources/application.yaml @@ -14,7 +14,6 @@ commons: reactive: true input-concurrency: 20 input-queue: "DEV.QUEUE.2" - input-queue-alias: "" input-queue-set-queue-manager: true # enable it to set queue manager using a temporary queue selector-mode: CONTEXT_PER_MESSAGE # CONTEXT_SHARED | CONTEXT_PER_MESSAGE ibm: diff --git a/examples/mq-reactive/README.md b/examples/mq-reactive/README.md index 8bad3af..0225517 100644 --- a/examples/mq-reactive/README.md +++ b/examples/mq-reactive/README.md @@ -6,6 +6,7 @@ You can do it with docker, please refer to [docker hub](https://hub.docker.com/r ```shell docker run -e LICENSE=accept -e MQ_QMGR_NAME=QM1 -p 1414:1414 -p 9443:9443 -d --name ibmmq -e MQ_APP_PASSWORD=passw0rd ibmcom/mq +docker run -e LICENSE=accept -e MQ_QMGR_NAME=QM2 -p 1415:1414 -p 9444:9443 -d --name ibmmq2 -e MQ_APP_PASSWORD=passw0rd ibmcom/mq ``` When MQ Server is running, run diff --git a/examples/mq-reactive/mq-reactive.gradle b/examples/mq-reactive/mq-reactive.gradle index 42a930d..b13c19a 100644 --- a/examples/mq-reactive/mq-reactive.gradle +++ b/examples/mq-reactive/mq-reactive.gradle @@ -1,5 +1,6 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' implementation 'org.springframework.boot:spring-boot-starter-webflux' implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation project(':commons-jms-mq') diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/app/config/Config.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/app/config/Config.java deleted file mode 100644 index a330370..0000000 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/app/config/Config.java +++ /dev/null @@ -1,39 +0,0 @@ -package co.com.bancolombia.jms.sample.app.config; - -import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; -import co.com.bancolombia.jms.sample.domain.model.Result; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.ibm.mq.spring.boot.MQConnectionFactoryCustomizer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import jakarta.jms.JMSException; -import jakarta.jms.JMSRuntimeException; - -import static com.ibm.msg.client.jakarta.wmq.common.CommonConstants.WMQ_CLIENT_RECONNECT; - -@Configuration -public class Config { - - @Bean - public ObjectMapper objectMapper() { - return new ObjectMapper(); - } - - // Sample connection factory customization - @Bean - public MQConnectionFactoryCustomizer cfCustomizer() { - return mqConnectionFactory -> { - try { - mqConnectionFactory.setClientReconnectOptions(WMQ_CLIENT_RECONNECT); - } catch (JMSException e) { - throw new JMSRuntimeException(e.getErrorCode(), e.getMessage(), e); - } - }; - } - - @Bean - public ReactiveReplyRouter resultReactiveReplyRouter() { - return new ReactiveReplyRouter<>(); - } -} diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/reqreply/MyRequestReply.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/reqreply/MyRequestReply.java deleted file mode 100644 index c6b9fd3..0000000 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/reqreply/MyRequestReply.java +++ /dev/null @@ -1,11 +0,0 @@ -package co.com.bancolombia.jms.sample.drivenadapters.reqreply; - -import co.com.bancolombia.commons.jms.mq.ReqReply; -import reactor.core.publisher.Mono; - -import jakarta.jms.Message; - -@ReqReply(requestQueue = "DEV.QUEUE.1", replyQueueTemp = "sample") -public interface MyRequestReply { - Mono requestReply(String message); -} diff --git a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/app/MainApplication.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/app/MainApplication.java similarity index 67% rename from examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/app/MainApplication.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/app/MainApplication.java index 9f4e03b..3824f7f 100644 --- a/examples/mq-mvc-app/src/main/java/co/com/bancolombia/jms/sample/noreactive/app/MainApplication.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/app/MainApplication.java @@ -1,9 +1,11 @@ -package co.com.bancolombia.jms.sample.noreactive.app; +package co.com.bancolombia.sample.app; +import co.com.bancolombia.commons.jms.mq.EnableMQGateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication(scanBasePackages = "co.com.bancolombia") +@EnableMQGateway(scanBasePackages = "co.com.bancolombia") public class MainApplication { public static void main(String[] args) { SpringApplication.run(MainApplication.class); diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/app/config/Config.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/app/config/Config.java new file mode 100644 index 0000000..7dd7a7e --- /dev/null +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/app/config/Config.java @@ -0,0 +1,85 @@ +package co.com.bancolombia.sample.app.config; + +import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; +import co.com.bancolombia.sample.domain.model.Result; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ibm.mq.jakarta.jms.MQConnectionFactory; +import com.ibm.mq.spring.boot.MQConfigurationProperties; +import com.ibm.mq.spring.boot.MQConnectionFactoryCustomizer; +import com.ibm.mq.spring.boot.MQConnectionFactoryFactory; +import jakarta.jms.ConnectionFactory; +import jakarta.jms.JMSException; +import jakarta.jms.JMSRuntimeException; +import lombok.SneakyThrows; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.jms.JmsProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.jms.connection.CachingConnectionFactory; + +import java.util.List; + +import static com.ibm.msg.client.jakarta.wmq.common.CommonConstants.WMQ_CLIENT_RECONNECT; + +@Configuration +@EnableConfigurationProperties({MQConfigurationProperties.class, JmsProperties.class}) +public class Config { + + @Bean + public ObjectMapper objectMapper() { + return new ObjectMapper(); + } + + // Sample connection factory customization + @Bean + public MQConnectionFactoryCustomizer cfCustomizer() { + return mqConnectionFactory -> { + try { + mqConnectionFactory.setClientReconnectOptions(WMQ_CLIENT_RECONNECT); + } catch (JMSException e) { + throw new JMSRuntimeException(e.getErrorCode(), e.getMessage(), e); + } + }; + } + + @Bean + public ReactiveReplyRouter resultReactiveReplyRouter() { + return new ReactiveReplyRouter<>(); + } + + @Bean + @Primary + @SneakyThrows + public ConnectionFactory cachingJmsConnectionFactory(MQConfigurationProperties properties, ObjectProvider> factoryCustomizers, JmsProperties jmsProperties) { + JmsProperties.Cache cacheProperties = jmsProperties.getCache(); + properties.setQueueManager("QM1"); + properties.setConnName("localhost(1414)"); + MQConnectionFactory wrappedConnectionFactory = createConnectionFactory(properties, factoryCustomizers); + CachingConnectionFactory connectionFactory = new CachingConnectionFactory(wrappedConnectionFactory); + connectionFactory.setCacheConsumers(cacheProperties.isConsumers()); + connectionFactory.setCacheProducers(cacheProperties.isProducers()); + connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize()); + return connectionFactory; + } + + @Bean + @SneakyThrows + public ConnectionFactory domainB(MQConfigurationProperties properties, ObjectProvider> factoryCustomizers, JmsProperties jmsProperties) { + JmsProperties.Cache cacheProperties = jmsProperties.getCache(); + properties.setQueueManager("QM2"); + properties.setConnName("localhost(1415)"); + MQConnectionFactory wrappedConnectionFactory = createConnectionFactory(properties, factoryCustomizers); + CachingConnectionFactory connectionFactory = new CachingConnectionFactory(wrappedConnectionFactory); + connectionFactory.setCacheConsumers(cacheProperties.isConsumers()); + connectionFactory.setCacheProducers(cacheProperties.isProducers()); + connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize()); + return connectionFactory; + } + + private static MQConnectionFactory createConnectionFactory(MQConfigurationProperties properties, ObjectProvider> factoryCustomizers) { + return (new MQConnectionFactoryFactory(properties, factoryCustomizers.getIfAvailable())).createConnectionFactory(MQConnectionFactory.class); + } + +} diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/app/config/UseCasesConfig.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/app/config/UseCasesConfig.java similarity index 90% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/app/config/UseCasesConfig.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/app/config/UseCasesConfig.java index f398db8..caaa511 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/app/config/UseCasesConfig.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/app/config/UseCasesConfig.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.app.config; +package co.com.bancolombia.sample.app.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/exceptions/ParseMessageException.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/exceptions/ParseMessageException.java similarity index 71% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/exceptions/ParseMessageException.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/exceptions/ParseMessageException.java index 7dfa20b..b8bc814 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/exceptions/ParseMessageException.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/exceptions/ParseMessageException.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.domain.exceptions; +package co.com.bancolombia.sample.domain.exceptions; public class ParseMessageException extends RuntimeException { public ParseMessageException(Throwable cause) { diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/exceptions/RelatedMessageNotFoundException.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/exceptions/RelatedMessageNotFoundException.java similarity index 56% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/exceptions/RelatedMessageNotFoundException.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/exceptions/RelatedMessageNotFoundException.java index 63f49cc..794c83f 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/exceptions/RelatedMessageNotFoundException.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/exceptions/RelatedMessageNotFoundException.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.domain.exceptions; +package co.com.bancolombia.sample.domain.exceptions; public class RelatedMessageNotFoundException extends RuntimeException { } diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/Request.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/Request.java similarity index 82% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/Request.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/Request.java index 41f3b69..17ee11d 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/Request.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/Request.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.domain.model; +package co.com.bancolombia.sample.domain.model; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/RequestGateway.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/RequestGateway.java similarity index 55% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/RequestGateway.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/RequestGateway.java index ee123f3..e9c0db1 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/RequestGateway.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/RequestGateway.java @@ -1,7 +1,8 @@ -package co.com.bancolombia.jms.sample.domain.model; +package co.com.bancolombia.sample.domain.model; import reactor.core.publisher.Mono; public interface RequestGateway { Mono doRequest(Request request); + Mono doRequestTmp(Request request); } diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/Result.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/Result.java similarity index 82% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/Result.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/Result.java index 10307db..1317009 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/Result.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/Result.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.domain.model; +package co.com.bancolombia.sample.domain.model; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/SenderGateway.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/SenderGateway.java similarity index 68% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/SenderGateway.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/SenderGateway.java index 7a8478d..cf63c6d 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/model/SenderGateway.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/model/SenderGateway.java @@ -1,4 +1,4 @@ -package co.com.bancolombia.jms.sample.domain.model; +package co.com.bancolombia.sample.domain.model; import reactor.core.publisher.Mono; diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/usecase/SampleReqReplyUseCase.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/usecase/SampleReqReplyUseCase.java similarity index 51% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/usecase/SampleReqReplyUseCase.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/usecase/SampleReqReplyUseCase.java index 5bf950b..d87bd71 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/usecase/SampleReqReplyUseCase.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/usecase/SampleReqReplyUseCase.java @@ -1,8 +1,8 @@ -package co.com.bancolombia.jms.sample.domain.usecase; +package co.com.bancolombia.sample.domain.usecase; -import co.com.bancolombia.jms.sample.domain.model.Request; -import co.com.bancolombia.jms.sample.domain.model.RequestGateway; -import co.com.bancolombia.jms.sample.domain.model.Result; +import co.com.bancolombia.sample.domain.model.Request; +import co.com.bancolombia.sample.domain.model.RequestGateway; +import co.com.bancolombia.sample.domain.model.Result; import lombok.AllArgsConstructor; import lombok.extern.log4j.Log4j2; import reactor.core.publisher.Mono; @@ -22,4 +22,12 @@ public Mono sendAndReceive() { .build()) .doOnSuccess(result -> log.info("Response got {}", result.toString())); } + + public Mono sendAndReceiveTmp() { + return gateway.doRequestTmp(Request.builder() + .id(UUID.randomUUID().toString()) + .createdAt(new Date().getTime()) + .build()) + .doOnSuccess(result -> log.info("Response got {}", result.toString())); + } } diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/usecase/SampleUseCase.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/usecase/SampleUseCase.java similarity index 75% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/usecase/SampleUseCase.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/usecase/SampleUseCase.java index bad7e09..4379639 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/domain/usecase/SampleUseCase.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/domain/usecase/SampleUseCase.java @@ -1,9 +1,9 @@ -package co.com.bancolombia.jms.sample.domain.usecase; +package co.com.bancolombia.sample.domain.usecase; import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; -import co.com.bancolombia.jms.sample.domain.model.Request; -import co.com.bancolombia.jms.sample.domain.model.SenderGateway; -import co.com.bancolombia.jms.sample.domain.model.Result; +import co.com.bancolombia.sample.domain.model.Request; +import co.com.bancolombia.sample.domain.model.Result; +import co.com.bancolombia.sample.domain.model.SenderGateway; import lombok.AllArgsConstructor; import lombok.extern.log4j.Log4j2; import reactor.core.publisher.Mono; diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/MyMQSender.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/MyMQSender.java similarity index 63% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/MyMQSender.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/MyMQSender.java index 70de67e..6405812 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/MyMQSender.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/MyMQSender.java @@ -1,31 +1,28 @@ -package co.com.bancolombia.jms.sample.drivenadapters; +package co.com.bancolombia.sample.drivenadapters; -import co.com.bancolombia.commons.jms.api.MQMessageSender; import co.com.bancolombia.commons.jms.api.MQQueuesContainer; -import co.com.bancolombia.commons.jms.mq.EnableMQMessageSender; -import co.com.bancolombia.jms.sample.domain.model.Request; -import co.com.bancolombia.jms.sample.domain.model.SenderGateway; +import co.com.bancolombia.sample.domain.model.Request; +import co.com.bancolombia.sample.domain.model.SenderGateway; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.jms.Message; import lombok.AllArgsConstructor; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import jakarta.jms.Message; - @Component @AllArgsConstructor -@EnableMQMessageSender public class MyMQSender implements SenderGateway { - private final MQMessageSender sender; +// private final MQMessageSender sender; + private final XDomainSender sender2; private final ObjectMapper mapper; private final MQQueuesContainer container; @Override public Mono send(Request request) { return Mono.fromCallable(() -> mapper.writeValueAsString(request)) - .flatMap(json -> sender.send(ctx -> { + .flatMap(json -> sender2.send(ctx -> { Message message = ctx.createTextMessage(json); - message.setJMSReplyTo(container.get("DEV.QUEUE.2")); + message.setJMSReplyTo(container.get("DEV.QUEUE.3")); return message; })); } diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/XDomainSender.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/XDomainSender.java new file mode 100644 index 0000000..c28c059 --- /dev/null +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/XDomainSender.java @@ -0,0 +1,8 @@ +package co.com.bancolombia.sample.drivenadapters; + +import co.com.bancolombia.commons.jms.api.MQMessageSender; +import co.com.bancolombia.commons.jms.mq.MQSender; + +@MQSender(connectionFactory = "domainB") +public interface XDomainSender extends MQMessageSender { +} diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReply.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReply.java new file mode 100644 index 0000000..3dee1e4 --- /dev/null +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReply.java @@ -0,0 +1,10 @@ +package co.com.bancolombia.sample.drivenadapters.reqreply; + +import co.com.bancolombia.commons.jms.api.MQRequestReply; +import co.com.bancolombia.commons.jms.mq.ReqReply; + +import static co.com.bancolombia.commons.jms.internal.models.MQListenerConfig.QueueType.FIXED; + +@ReqReply(requestQueue = "DEV.QUEUE.1", replyQueue = "DEV.QUEUE.2", queueType = FIXED, connectionFactory = "domainB") +public interface MyRequestReply extends MQRequestReply { +} diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/reqreply/MyRequestReplyAdapter.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReplyAdapter.java similarity index 62% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/reqreply/MyRequestReplyAdapter.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReplyAdapter.java index 02036db..6900506 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/drivenadapters/reqreply/MyRequestReplyAdapter.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReplyAdapter.java @@ -1,32 +1,38 @@ -package co.com.bancolombia.jms.sample.drivenadapters.reqreply; +package co.com.bancolombia.sample.drivenadapters.reqreply; -import co.com.bancolombia.commons.jms.mq.EnableReqReply; -import co.com.bancolombia.jms.sample.domain.model.Request; -import co.com.bancolombia.jms.sample.domain.model.RequestGateway; -import co.com.bancolombia.jms.sample.domain.model.Result; +import co.com.bancolombia.sample.domain.model.Request; +import co.com.bancolombia.sample.domain.model.RequestGateway; +import co.com.bancolombia.sample.domain.model.Result; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.jms.Message; +import jakarta.jms.TextMessage; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import jakarta.jms.Message; -import jakarta.jms.TextMessage; import java.util.Date; @Log4j2 @Component @AllArgsConstructor -@EnableReqReply(scanBasePackages = "co.com.bancolombia") public class MyRequestReplyAdapter implements RequestGateway { - private final MyRequestReply requestReply; + private final MyRequestReply requestReply; // domainB + private final MyRequestReplyTmp requestReplyTmp; // default domain private final ObjectMapper mapper; @Override public Mono doRequest(Request request) { return Mono.fromCallable(() -> mapper.writeValueAsString(request)) - .flatMap(requestReply::requestReply) + .flatMap(requestReplyTmp::requestReply) + .map(this::mapResponse); + } + + @Override + public Mono doRequestTmp(Request request) { + return Mono.fromCallable(() -> mapper.writeValueAsString(request)) + .flatMap(requestReplyTmp::requestReply) .map(this::mapResponse); } diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReplyTmp.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReplyTmp.java new file mode 100644 index 0000000..51b6d9e --- /dev/null +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/drivenadapters/reqreply/MyRequestReplyTmp.java @@ -0,0 +1,8 @@ +package co.com.bancolombia.sample.drivenadapters.reqreply; + +import co.com.bancolombia.commons.jms.api.MQRequestReply; +import co.com.bancolombia.commons.jms.mq.ReqReply; + +@ReqReply(requestQueue = "DEV.QUEUE.1", replyQueue = "alias", connectionFactory = "") +public interface MyRequestReplyTmp extends MQRequestReply { +} diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/entrypoints/MyMQListener.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/entrypoints/MyMQListener.java similarity index 85% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/entrypoints/MyMQListener.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/entrypoints/MyMQListener.java index e3f06df..1e8e9cd 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/entrypoints/MyMQListener.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/entrypoints/MyMQListener.java @@ -1,19 +1,19 @@ -package co.com.bancolombia.jms.sample.entrypoints; +package co.com.bancolombia.sample.entrypoints; import co.com.bancolombia.commons.jms.mq.MQListener; import co.com.bancolombia.commons.jms.utils.ReactiveReplyRouter; -import co.com.bancolombia.jms.sample.domain.model.Request; -import co.com.bancolombia.jms.sample.domain.model.Result; +import co.com.bancolombia.sample.domain.model.Request; +import co.com.bancolombia.sample.domain.model.Result; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.jms.JMSException; +import jakarta.jms.Message; +import jakarta.jms.TextMessage; import lombok.AllArgsConstructor; import lombok.extern.log4j.Log4j2; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; -import jakarta.jms.JMSException; -import jakarta.jms.Message; -import jakarta.jms.TextMessage; import java.util.Date; @Log4j2 @@ -23,7 +23,7 @@ public class MyMQListener { private final ReactiveReplyRouter useCase; private final ObjectMapper mapper; - @MQListener + @MQListener(value = "DEV.QUEUE.3", connectionFactory = "domainB") public Mono process(Message message) throws JMSException, JsonProcessingException { log.info("Received and processing"); TextMessage textMessage = (TextMessage) message; diff --git a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/entrypoints/Rest.java b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/entrypoints/Rest.java similarity index 67% rename from examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/entrypoints/Rest.java rename to examples/mq-reactive/src/main/java/co/com/bancolombia/sample/entrypoints/Rest.java index 11a577f..04ad87e 100644 --- a/examples/mq-reactive/src/main/java/co/com/bancolombia/jms/sample/entrypoints/Rest.java +++ b/examples/mq-reactive/src/main/java/co/com/bancolombia/sample/entrypoints/Rest.java @@ -1,8 +1,8 @@ -package co.com.bancolombia.jms.sample.entrypoints; +package co.com.bancolombia.sample.entrypoints; -import co.com.bancolombia.jms.sample.domain.model.Result; -import co.com.bancolombia.jms.sample.domain.usecase.SampleReqReplyUseCase; -import co.com.bancolombia.jms.sample.domain.usecase.SampleUseCase; +import co.com.bancolombia.sample.domain.model.Result; +import co.com.bancolombia.sample.domain.usecase.SampleReqReplyUseCase; +import co.com.bancolombia.sample.domain.usecase.SampleUseCase; import lombok.AllArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -24,8 +24,10 @@ public RouterFunction route() { return RouterFunctions .route(RequestPredicates.GET("/api/mq") .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), request -> sample()) - .andRoute(RequestPredicates.GET("/api/mq/reqreply") - .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), request -> sampleReqReply()); + .andRoute(RequestPredicates.GET("/api/mq/reqreply/fixed") + .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), request -> sampleReqReply()) + .andRoute(RequestPredicates.GET("/api/mq/reqreply/tmp") + .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), request -> sampleReqReplyTmp()); } public Mono sample() { @@ -39,4 +41,10 @@ public Mono sampleReqReply() { .contentType(MediaType.APPLICATION_JSON) .body(sampleReqReplyUseCase.sendAndReceive(), Result.class); } + + public Mono sampleReqReplyTmp() { + return ServerResponse.ok() + .contentType(MediaType.APPLICATION_JSON) + .body(sampleReqReplyUseCase.sendAndReceiveTmp(), Result.class); + } } diff --git a/examples/mq-reactive/src/main/resources/application.yaml b/examples/mq-reactive/src/main/resources/application.yaml index b56b0fd..e1e6250 100644 --- a/examples/mq-reactive/src/main/resources/application.yaml +++ b/examples/mq-reactive/src/main/resources/application.yaml @@ -5,16 +5,15 @@ spring: name: "mq-reactive" logging: level: - root: WARN + root: INFO commons: jms: - output-concurrency: 2 + output-concurrency: 1 output-queue: "DEV.QUEUE.1" producer-ttl: 60 reactive: true - input-concurrency: 2 + input-concurrency: 1 input-queue: "DEV.QUEUE.2" - input-queue-alias: "" ibm: mq: channel: "DEV.APP.SVRCONN" diff --git a/main.gradle b/main.gradle index 4f610eb..62e38a5 100644 --- a/main.gradle +++ b/main.gradle @@ -59,9 +59,9 @@ subprojects { testAnnotationProcessor 'org.projectlombok:lombok' testCompileOnly 'org.projectlombok:lombok' testImplementation 'io.projectreactor:reactor-test' - testImplementation platform('org.junit:junit-bom:5.7.0') + testImplementation platform('org.junit:junit-bom:5.10.0') testImplementation 'org.junit.jupiter:junit-jupiter-engine' - testImplementation 'org.mockito:mockito-junit-jupiter:3.7.7' + testImplementation 'org.mockito:mockito-junit-jupiter:5.10.0' } test { @@ -89,7 +89,7 @@ subprojects { ] } - check.dependsOn dependencyCheckAggregate +// check.dependsOn dependencyCheckAggregate dependencyCheck { format = 'JSON'