From 2323fad80d9ccad4ac89467cf6d2a49bfe44bf88 Mon Sep 17 00:00:00 2001 From: Ush Shukla <21085773+Ushnash@users.noreply.github.com> Date: Tue, 19 Dec 2023 12:44:22 -0600 Subject: [PATCH 1/5] adding ibmmq plugin --- service/application/pom.xml | 5 + .../src/main/resources/application.yml | 340 ++++++++++-------- service/ibmmq-plugin/pom.xml | 77 ++++ .../agent/plugin/ibmmq/IbmMqApplication.java | 14 + .../ibmmq/client/http/IbmMqHttpClient.java | 19 + .../ibmmq/client/http/IbmMqQueueResponse.java | 12 + .../http/IbmMqSubscriptionResponse.java | 12 + .../manager/client/IbmMqClientConfigImpl.java | 21 ++ .../client/IbmMqClientManagerImpl.java | 70 ++++ .../ibmmq/processor/IbmMqQueueProcessor.java | 40 +++ .../processor/IbmMqSubscriptionProcessor.java | 40 +++ .../processor/event/IbmMqQueueEvent.java | 14 + .../event/IbmMqSubscriptionEvent.java | 15 + .../delegate/IbmMqRouteDelegateImpl.java | 58 +++ .../ibmmq/route/enumeration/IbmMqRouteId.java | 12 + .../route/enumeration/IbmMqRouteType.java | 12 + .../route/enumeration/IbmMqScanType.java | 8 + .../handler/IbmMqQueueDataPublisherRoute.java | 23 ++ .../IbmMqSubscriptionDataPublisherRoute.java | 23 ++ .../plugin/ibmmq/IbmMqApplicationTests.java | 116 ++++++ .../agent/plugin/ibmmq/IbmMqTestConfig.java | 40 +++ .../delegate/IbmMqRouteDelegateImplTests.java | 61 ++++ .../src/test/resources/queue_response.json | 42 +++ .../test/resources/subscription_response.json | 79 ++++ service/pom.xml | 1 + 25 files changed, 997 insertions(+), 157 deletions(-) create mode 100644 service/ibmmq-plugin/pom.xml create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplication.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqQueueResponse.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqSubscriptionResponse.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqQueueProcessor.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqSubscriptionProcessor.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqQueueEvent.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqSubscriptionEvent.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImpl.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteId.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteType.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqScanType.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqQueueDataPublisherRoute.java create mode 100644 service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqSubscriptionDataPublisherRoute.java create mode 100644 service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplicationTests.java create mode 100644 service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqTestConfig.java create mode 100644 service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImplTests.java create mode 100644 service/ibmmq-plugin/src/test/resources/queue_response.json create mode 100644 service/ibmmq-plugin/src/test/resources/subscription_response.json diff --git a/service/application/pom.xml b/service/application/pom.xml index 6c632cf9..ca7f2291 100644 --- a/service/application/pom.xml +++ b/service/application/pom.xml @@ -248,6 +248,11 @@ terraform-plugin 1.3.2-SNAPSHOT + + com.solace.maas + ibmmq-plugin + 0.0.2-SNAPSHOT + io.micrometer diff --git a/service/application/src/main/resources/application.yml b/service/application/src/main/resources/application.yml index 31385b9a..c0bba152 100644 --- a/service/application/src/main/resources/application.yml +++ b/service/application/src/main/resources/application.yml @@ -88,164 +88,190 @@ eventPortal: password: ${EP_GATEWAY_PASSWORD} clientName: runtime_agent_${EP_RUNTIME_AGENT_ID} # 'client_' + runtimeAgentId -# Below is an example of how to set up messaging service configuration in the application.yml file. -#plugins: -# resources: -# # Confluent Schema Registry No Auth example -# - id: someConfluentId -# name: no auth confluent example -# type: confluent_schema_registry -# relatedServices: -# - id1 -# - id2 -# - id3 -# connections: -# - name: myConfluentNoAuth -# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} -# # Confluent Schema Registry Basic Auth example -# - id: someConfluentId -# name: no auth confluent example -# type: confluent_schema_registry -# relatedServices: -# - id1 -# connections: -# - name: myConfluentBasicAuth -# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} -# authentication: -# - protocol: BASIC -# credentials: -# - properties: -# - name: username -# value: ${CONFLUENT_USERNAME} -# - name: password -# value: ${CONFLUENT_PASSWORD} -# source: ENVIRONMENT_VARIABLE -# operations: -# - name: ALL -# # Confluent Schema Registry Basic Auth With SSL example -# - id: someConfluentId -# name: no auth confluent example -# type: confluent_schema_registry -# relatedServices: -# - id1 -# connections: -# - name: myConfluentBasicAuthWithSSL -# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} -# authentication: -# - protocol: BASIC_SSL -# credentials: -# - properties: -# - name: username -# value: ${CONFLUENT_USERNAME} -# - name: password -# value: ${CONFLUENT_PASSWORD} -# - name: ssl.truststore.location -# value: ${TRUSTSTORE_LOCATION} -# - name: ssl.truststore.password -# value: ${TRUSTSTORE_PASSWORD} -# source: ENVIRONMENT_VARIABLE -# operations: -# - name: ALL -# # Confluent Schema Registry Basic Auth With mTLS example -# - id: someConfluentId -# name: Basic Auth With mTLS example -# type: confluent_schema_registry -# relatedServices: -# - id1 -# connections: -# - name: myConfluentBasicAuthWithMTLS -# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} -# authentication: -# - protocol: BASIC_MTLS -# credentials: -# - properties: -# - name: username -# value: ${CONFLUENT_USERNAME} -# - name: password -# value: ${CONFLUENT_PASSWORD} -# - name: ssl.truststore.location -# value: ${TRUSTSTORE_LOCATION} -# - name: ssl.truststore.password -# value: ${TRUSTSTORE_PASSWORD} -# - name: ssl.keystore.location -# value: ${KEYSTORE_LOCATION} -# - name: ssl.keystore.password -# value: ${KEYSTORE_PASSWORD} -# - name: ssl.key.password -# value: ${KEY_PASSWORD} -# source: ENVIRONMENT_VARIABLE -# operations: -# - name: ALL -# # Confluent Schema Registry TLS example -# - id: someConfluentId -# name: no auth confluent example -# type: confluent_schema_registry -# relatedServices: -# - id1 -# connections: -# - name: myConfluentTLS -# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} -# authentication: -# - protocol: TLS -# credentials: -# - properties: -# - name: ssl.truststore.location -# value: ${TRUSTSTORE_LOCATION} -# - name: ssl.truststore.password -# value: ${TRUSTSTORE_PASSWORD} -# source: ENVIRONMENT_VARIABLE -# operations: -# - name: ALL -# # Confluent Schema Registry MTLS example -# - id: someConfluentId -# name: no auth confluent example -# type: confluent_schema_registry -# relatedServices: -# - id1 -# connections: -# - name: myConfluentMTLS -# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} -# authentication: -# - protocol: MTLS -# credentials: -# - properties: -# - name: ssl.truststore.location -# value: ${TRUSTSTORE_LOCATION} -# - name: ssl.truststore.password -# value: ${TRUSTSTORE_PASSWORD} -# - name: ssl.keystore.password -# value: ${KEYSTORE_PASSWORD} -# - name: ssl.keystore.location -# value: ${KEYSTORE_LOCATION} -# - name: ssl.key.password -# value: ${KEY_PASSWORD} -# source: ENVIRONMENT_VARIABLE -# operations: -# - name: ALL -# # Solace example -# - id: solaceDefaultService -# type: SOLACE -# name: staging service -# connections: -# - name: mySolaceServiceSemp -# url: ${SOLACE_SEMP_URL} -# authentication: -# - protocol: SEMP -# credentials: -# - source: ENVIRONMENT_VARIABLE -# operations: -# - name: ALL -# properties: -# - name: username -# value: ${SOLACE_SEMP_USERNAME} -# - name: password -# value: ${SOLACE_SEMP_PASSWORD} -# properties: -# - name: msgVpn -# value: ${SOLACE_VPN_NAME} -# - name: sempPageSize -# value: 100 +plugins: + resources: + # IBMMQ example + - id: ibmmqDefaultService + type: IBMMQ + name: test service + connections: + - name: ibmmqCloudService + url: https://web-qm1-5bc5.qm.us-south.mq.appdomain.cloud/ibmmq/rest/v1/admin/qmgr/QM1 + authentication: + - protocol: BASIC + credentials: + - source: + properties: + - name: username + value: ush + - name: password + value: E5J8yGHjPTErikzOVZ0FiloP47FooNKQSTcTx5jQE-oM + operations: + - name: IBMMQ_QUEUE + # properties: + # - name: msgVpn + # value: ${SOLACE_VPN_NAME} + # - name: sempPageSize + # value: 100 + # Below is an example of how to set up messaging service configuration in the application.yml file. + + #plugins: + # resources: + # # Confluent Schema Registry No Auth example + # - id: someConfluentId + # name: no auth confluent example + # type: confluent_schema_registry + # relatedServices: + # - id1 + # - id2 + # - id3 + # connections: + # - name: myConfluentNoAuth + # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} + # # Confluent Schema Registry Basic Auth example + # - id: someConfluentId + # name: no auth confluent example + # type: confluent_schema_registry + # relatedServices: + # - id1 + # connections: + # - name: myConfluentBasicAuth + # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} + # authentication: + # - protocol: BASIC + # credentials: + # - properties: + # - name: username + # value: ${CONFLUENT_USERNAME} + # - name: password + # value: ${CONFLUENT_PASSWORD} + # source: ENVIRONMENT_VARIABLE + # operations: + # - name: ALL + # # Confluent Schema Registry Basic Auth With SSL example + # - id: someConfluentId + # name: no auth confluent example + # type: confluent_schema_registry + # relatedServices: + # - id1 + # connections: + # - name: myConfluentBasicAuthWithSSL + # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} + # authentication: + # - protocol: BASIC_SSL + # credentials: + # - properties: + # - name: username + # value: ${CONFLUENT_USERNAME} + # - name: password + # value: ${CONFLUENT_PASSWORD} + # - name: ssl.truststore.location + # value: ${TRUSTSTORE_LOCATION} + # - name: ssl.truststore.password + # value: ${TRUSTSTORE_PASSWORD} + # source: ENVIRONMENT_VARIABLE + # operations: + # - name: ALL + # # Confluent Schema Registry Basic Auth With mTLS example + # - id: someConfluentId + # name: Basic Auth With mTLS example + # type: confluent_schema_registry + # relatedServices: + # - id1 + # connections: + # - name: myConfluentBasicAuthWithMTLS + # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} + # authentication: + # - protocol: BASIC_MTLS + # credentials: + # - properties: + # - name: username + # value: ${CONFLUENT_USERNAME} + # - name: password + # value: ${CONFLUENT_PASSWORD} + # - name: ssl.truststore.location + # value: ${TRUSTSTORE_LOCATION} + # - name: ssl.truststore.password + # value: ${TRUSTSTORE_PASSWORD} + # - name: ssl.keystore.location + # value: ${KEYSTORE_LOCATION} + # - name: ssl.keystore.password + # value: ${KEYSTORE_PASSWORD} + # - name: ssl.key.password + # value: ${KEY_PASSWORD} + # source: ENVIRONMENT_VARIABLE + # operations: + # - name: ALL + # # Confluent Schema Registry TLS example + # - id: someConfluentId + # name: no auth confluent example + # type: confluent_schema_registry + # relatedServices: + # - id1 + # connections: + # - name: myConfluentTLS + # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} + # authentication: + # - protocol: TLS + # credentials: + # - properties: + # - name: ssl.truststore.location + # value: ${TRUSTSTORE_LOCATION} + # - name: ssl.truststore.password + # value: ${TRUSTSTORE_PASSWORD} + # source: ENVIRONMENT_VARIABLE + # operations: + # - name: ALL + # # Confluent Schema Registry MTLS example + # - id: someConfluentId + # name: no auth confluent example + # type: confluent_schema_registry + # relatedServices: + # - id1 + # connections: + # - name: myConfluentMTLS + # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} + # authentication: + # - protocol: MTLS + # credentials: + # - properties: + # - name: ssl.truststore.location + # value: ${TRUSTSTORE_LOCATION} + # - name: ssl.truststore.password + # value: ${TRUSTSTORE_PASSWORD} + # - name: ssl.keystore.password + # value: ${KEYSTORE_PASSWORD} + # - name: ssl.keystore.location + # value: ${KEYSTORE_LOCATION} + # - name: ssl.key.password + # value: ${KEY_PASSWORD} + # source: ENVIRONMENT_VARIABLE + # operations: + # - name: ALL + # Solace example + - id: solaceDefaultService + type: SOLACE + name: staging service + connections: + - name: mySolaceServiceSemp + url: ${SOLACE_SEMP_URL} + authentication: + - protocol: SEMP + credentials: + - source: ENVIRONMENT_VARIABLE + operations: + - name: ALL + properties: + - name: username + value: ${SOLACE_SEMP_USERNAME} + - name: password + value: ${SOLACE_SEMP_PASSWORD} + properties: + - name: msgVpn + value: ${SOLACE_VPN_NAME} + - name: sempPageSize + value: 100 # # MTLS example # - id: kafkaMTLSServiceExample # name: mtls kafka cluster example diff --git a/service/ibmmq-plugin/pom.xml b/service/ibmmq-plugin/pom.xml new file mode 100644 index 00000000..1c2bd01f --- /dev/null +++ b/service/ibmmq-plugin/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + com.solace.maas + maas-event-management-agent-parent + 1.3.2-SNAPSHOT + + + ibmmq-plugin + 0.0.2-SNAPSHOT + Solace Event Management Agent - IBMMQ Plugin + Solace Event Management Agent - IBMMQ Plugin + + + ${java.version} + ${java.version} + UTF-8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.cloud + spring-cloud-starter-openfeign + 4.0.4 + + + io.github.openfeign + feign-jackson + 13.0 + + + com.solace.maas + plugin + 1.3.2-SNAPSHOT + + + org.apache.camel + camel-jackson + ${camel.version} + + + + + org.springframework.boot + spring-boot-starter-test + test + + + com.squareup.okhttp3 + okhttp + 4.0.1 + test + + + com.squareup.okhttp3 + mockwebserver + 4.0.1 + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplication.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplication.java new file mode 100644 index 00000000..5ae4c5b1 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplication.java @@ -0,0 +1,14 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +@SpringBootApplication +@EnableFeignClients +public class IbmMqApplication { + + public static void main(String[] args) { + SpringApplication.run(IbmMqApplication.class, args); + } +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java new file mode 100644 index 00000000..292bf8c2 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java @@ -0,0 +1,19 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; + +/** + * Uses OpenFeign to create the MQ REST API Admin Client. + */ +@FeignClient(name = "ibmmq-http-client") +public interface IbmMqHttpClient { + + /*Gets all queues on a given queue manager*/ + @GetMapping("/queue") + IbmMqQueueResponse getQueues(); + + /*Gets all subscriptions (topics) on a given queue manager*/ + @GetMapping("/subscription") + IbmMqSubscriptionResponse getSubscriptions(); +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqQueueResponse.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqQueueResponse.java new file mode 100644 index 00000000..1d6f7da3 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqQueueResponse.java @@ -0,0 +1,12 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event.IbmMqQueueEvent; +import lombok.Getter; + +import java.util.List; + +@Getter +public class IbmMqQueueResponse { + + private List queue; +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqSubscriptionResponse.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqSubscriptionResponse.java new file mode 100644 index 00000000..bb54df2f --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqSubscriptionResponse.java @@ -0,0 +1,12 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event.IbmMqSubscriptionEvent; +import lombok.Data; + +import java.util.List; + +@Data +public class IbmMqSubscriptionResponse { + + List subscription; +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java new file mode 100644 index 00000000..e710520a --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java @@ -0,0 +1,21 @@ +/** + * + */ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.manager.client; + +import com.solace.maas.ep.event.management.agent.plugin.manager.client.MessagingServiceClientConfig; +import org.springframework.context.annotation.Configuration; + +/** + * + */ +@Configuration +public class IbmMqClientConfigImpl extends MessagingServiceClientConfig { + + private static final String SERVICE_NAME = "IBMMQ"; + + protected IbmMqClientConfigImpl() { + super(SERVICE_NAME, new IbmMqClientManagerImpl()); + } + +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java new file mode 100644 index 00000000..15bfb4e9 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java @@ -0,0 +1,70 @@ +/** + * + */ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.manager.client; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqHttpClient; +import com.solace.maas.ep.event.management.agent.plugin.manager.client.MessagingServiceClientManager; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.AuthenticationDetailsEvent; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.ConnectionDetailsEvent; +import com.solace.maas.ep.event.management.agent.plugin.util.MessagingServiceConfigurationUtil; +import feign.Feign; +import feign.auth.BasicAuthRequestInterceptor; +import feign.jackson.JacksonDecoder; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.openfeign.support.SpringMvcContract; +import org.springframework.stereotype.Component; + +import java.util.NoSuchElementException; + +/** + * + */ +@Slf4j +@Data +@Component +public class IbmMqClientManagerImpl implements MessagingServiceClientManager { + + public IbmMqClientManagerImpl() { + } + + @Override + public IbmMqHttpClient getClient(ConnectionDetailsEvent connectionDetailsEvent) { + + log.trace("Creating IBMMQ-HTTP client for messaging service [{}].", + connectionDetailsEvent.getMessagingServiceId()); + + AuthenticationDetailsEvent authenticationDetailsEvent = connectionDetailsEvent.getAuthenticationDetails() + .stream() + .findFirst().orElseThrow(() -> { + String message = String.format("Could not find authentication details for service with id [%s].", + connectionDetailsEvent.getMessagingServiceId()); + log.error(message); + return new NoSuchElementException(message); + }); + + String username = MessagingServiceConfigurationUtil.getUsername(authenticationDetailsEvent); + String password = MessagingServiceConfigurationUtil.getPassword(authenticationDetailsEvent); + String url = connectionDetailsEvent.getUrl(); + + //so that we can configure Jackson + ObjectMapper mapper = JsonMapper + .builder() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .build(); + + + IbmMqHttpClient client = Feign.builder() + .requestInterceptor(new BasicAuthRequestInterceptor(username, password)) + .contract(new SpringMvcContract()) + .decoder(new JacksonDecoder(mapper)) + .target(IbmMqHttpClient.class, url); + + return client; + } + +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqQueueProcessor.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqQueueProcessor.java new file mode 100644 index 00000000..c580df25 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqQueueProcessor.java @@ -0,0 +1,40 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor; + +import com.solace.maas.ep.event.management.agent.plugin.constants.RouteConstants; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqHttpClient; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqQueueResponse; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event.IbmMqQueueEvent; +import com.solace.maas.ep.event.management.agent.plugin.processor.base.ResultProcessorImpl; +import com.solace.maas.ep.event.management.agent.plugin.service.MessagingServiceDelegateService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +@Slf4j +@Component +public class IbmMqQueueProcessor extends ResultProcessorImpl, Void> { + private final MessagingServiceDelegateService messagingServiceDelegateService; + + @Autowired + public IbmMqQueueProcessor(MessagingServiceDelegateService messagingServiceDelegateService) { + super(); + this.messagingServiceDelegateService = messagingServiceDelegateService; + log.debug("### In Queue Processor ###"); + } + + @Override + public List handleEvent(Map properties, Void body) throws Exception { + String messagingServiceId = (String) properties.get(RouteConstants.MESSAGING_SERVICE_ID); + + IbmMqHttpClient client = messagingServiceDelegateService.getMessagingServiceClient(messagingServiceId); + + log.info("### Invoking Queue endpoint for messaging service with ID {}", messagingServiceId); + IbmMqQueueResponse queueList = client.getQueues(); + + return queueList.getQueue(); + } + +} \ No newline at end of file diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqSubscriptionProcessor.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqSubscriptionProcessor.java new file mode 100644 index 00000000..e953e4da --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqSubscriptionProcessor.java @@ -0,0 +1,40 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor; + +import com.solace.maas.ep.event.management.agent.plugin.constants.RouteConstants; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqHttpClient; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqSubscriptionResponse; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event.IbmMqSubscriptionEvent; +import com.solace.maas.ep.event.management.agent.plugin.processor.base.ResultProcessorImpl; +import com.solace.maas.ep.event.management.agent.plugin.service.MessagingServiceDelegateService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +@Slf4j +@Component +public class IbmMqSubscriptionProcessor extends ResultProcessorImpl, Void> { + private final MessagingServiceDelegateService messagingServiceDelegateService; + + @Autowired + public IbmMqSubscriptionProcessor(MessagingServiceDelegateService messagingServiceDelegateService) { + super(); + this.messagingServiceDelegateService = messagingServiceDelegateService; + log.debug("### In Subscription Processor ###"); + } + + @Override + public List handleEvent(Map properties, Void body) throws Exception { + String messagingServiceId = (String) properties.get(RouteConstants.MESSAGING_SERVICE_ID); + + IbmMqHttpClient client = messagingServiceDelegateService.getMessagingServiceClient(messagingServiceId); + + log.info("### Invoking Queue endpoint for messaging service with ID {}", messagingServiceId); + IbmMqSubscriptionResponse subscriptionList = client.getSubscriptions(); + + return subscriptionList.getSubscription(); + } + +} \ No newline at end of file diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqQueueEvent.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqQueueEvent.java new file mode 100644 index 00000000..08b50a82 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqQueueEvent.java @@ -0,0 +1,14 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event; + +import lombok.Getter; + +import java.io.Serializable; + +@Getter +public class IbmMqQueueEvent implements Serializable { + + private static final long serialVersionUID = 7693606299215131178L; + + private String name; + private String type; +} \ No newline at end of file diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqSubscriptionEvent.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqSubscriptionEvent.java new file mode 100644 index 00000000..0067feb0 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqSubscriptionEvent.java @@ -0,0 +1,15 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.event; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class IbmMqSubscriptionEvent implements Serializable { + + private static final long serialVersionUID = 7693606299215131178L; + + private String resolvedTopicString; + private String name; + private String id; +} \ No newline at end of file diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImpl.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImpl.java new file mode 100644 index 00000000..dfd69db7 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImpl.java @@ -0,0 +1,58 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.delegate; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteId; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteType; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqScanType; +import com.solace.maas.ep.event.management.agent.plugin.jacoco.ExcludeFromJacocoGeneratedReport; +import com.solace.maas.ep.event.management.agent.plugin.route.RouteBundle; +import com.solace.maas.ep.event.management.agent.plugin.route.delegate.base.MessagingServiceRouteDelegateImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@ExcludeFromJacocoGeneratedReport +@SuppressWarnings("CPD-START") +@Component +@Slf4j +public class IbmMqRouteDelegateImpl extends MessagingServiceRouteDelegateImpl { + + public IbmMqRouteDelegateImpl() { + super("IBMMQ"); + log.debug("### PLUGIN `IBMMQ` HAS LOADED ###"); + } + + @Override + public List generateRouteList(List destinations, List recipients, + String scanType, String messagingServiceId) { + List result = new ArrayList<>(); + + switch (IbmMqScanType.valueOf(scanType)) { + case IBMMQ_ALL: + result.add(queueRouteBundle(destinations, recipients, messagingServiceId)); + result.add(subscriptionRouteBundle(destinations, recipients, messagingServiceId)); + break; + case IBMMQ_QUEUE: + result.add(queueRouteBundle(destinations, recipients, messagingServiceId)); + break; + case IBMMQ_SUBSCRIPTION: + result.add(subscriptionRouteBundle(destinations, recipients, messagingServiceId)); + break; + } + + return result; + } + + private RouteBundle queueRouteBundle(List destinations, List recipients, + String messagingServiceId) { + return createRouteBundle(destinations, recipients, IbmMqRouteType.IBMMQ_QUEUE.label, messagingServiceId, + IbmMqRouteId.IBMMQ_QUEUE.label, true); + } + + private RouteBundle subscriptionRouteBundle(List destinations, List recipients, + String messagingServiceId) { + return createRouteBundle(destinations, recipients, IbmMqRouteType.IBMMQ_SUBSCRIPTION.label, messagingServiceId, + IbmMqRouteId.IBMMQ_SUBSCRIPTION.label, false); + } +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteId.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteId.java new file mode 100644 index 00000000..fbdb27ea --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteId.java @@ -0,0 +1,12 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration; + +public enum IbmMqRouteId { + IBMMQ_QUEUE("IBMMQQueueListing"), + IBMMQ_SUBSCRIPTION("IBMMQSubscriptionListing"); + + public final String label; + + IbmMqRouteId(String label) { + this.label = label; + } +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteType.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteType.java new file mode 100644 index 00000000..0601b43f --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqRouteType.java @@ -0,0 +1,12 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration; + +public enum IbmMqRouteType { + IBMMQ_QUEUE("queueListing"), + IBMMQ_SUBSCRIPTION("subscriptionListing"); + + public final String label; + + IbmMqRouteType(String label) { + this.label = label; + } +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqScanType.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqScanType.java new file mode 100644 index 00000000..d4a2b90e --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/enumeration/IbmMqScanType.java @@ -0,0 +1,8 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration; + +public enum IbmMqScanType { + + IBMMQ_ALL, + IBMMQ_QUEUE, + IBMMQ_SUBSCRIPTION; +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqQueueDataPublisherRoute.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqQueueDataPublisherRoute.java new file mode 100644 index 00000000..69029628 --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqQueueDataPublisherRoute.java @@ -0,0 +1,23 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.handler; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.IbmMqQueueProcessor; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteId; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteType; +import com.solace.maas.ep.event.management.agent.plugin.processor.ScanTypeDescendentsProcessor; +import com.solace.maas.ep.event.management.agent.plugin.processor.logging.MDCProcessor; +import com.solace.maas.ep.event.management.agent.plugin.route.handler.base.DataPublisherRouteBuilder; +import com.solace.maas.ep.event.management.agent.plugin.route.manager.RouteManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class IbmMqQueueDataPublisherRoute extends DataPublisherRouteBuilder { + + @Autowired + public IbmMqQueueDataPublisherRoute(IbmMqQueueProcessor processor, RouteManager routeManager, + MDCProcessor mdcProcessor, ScanTypeDescendentsProcessor scanTypeDescendentsProcessor) { + super(processor, IbmMqRouteId.IBMMQ_QUEUE.label, IbmMqRouteType.IBMMQ_QUEUE.label, + routeManager, mdcProcessor, scanTypeDescendentsProcessor); + + } +} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqSubscriptionDataPublisherRoute.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqSubscriptionDataPublisherRoute.java new file mode 100644 index 00000000..855e6c3c --- /dev/null +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/handler/IbmMqSubscriptionDataPublisherRoute.java @@ -0,0 +1,23 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.handler; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.processor.IbmMqSubscriptionProcessor; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteId; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqRouteType; +import com.solace.maas.ep.event.management.agent.plugin.processor.ScanTypeDescendentsProcessor; +import com.solace.maas.ep.event.management.agent.plugin.processor.logging.MDCProcessor; +import com.solace.maas.ep.event.management.agent.plugin.route.handler.base.DataPublisherRouteBuilder; +import com.solace.maas.ep.event.management.agent.plugin.route.manager.RouteManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class IbmMqSubscriptionDataPublisherRoute extends DataPublisherRouteBuilder { + + @Autowired + public IbmMqSubscriptionDataPublisherRoute(IbmMqSubscriptionProcessor processor, RouteManager routeManager, + MDCProcessor mdcProcessor, ScanTypeDescendentsProcessor scanTypeDescendentsProcessor) { + super(processor, IbmMqRouteId.IBMMQ_SUBSCRIPTION.label, IbmMqRouteType.IBMMQ_SUBSCRIPTION.label, + routeManager, mdcProcessor, scanTypeDescendentsProcessor); + } + +} diff --git a/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplicationTests.java b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplicationTests.java new file mode 100644 index 00000000..5370ae56 --- /dev/null +++ b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplicationTests.java @@ -0,0 +1,116 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqHttpClient; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqQueueResponse; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqSubscriptionResponse; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.manager.client.IbmMqClientManagerImpl; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.AuthenticationDetailsEvent; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.ConnectionDetailsEvent; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.CredentialDetailsEvent; +import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.EventProperty; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import org.junit.Assert; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = IbmMqTestConfig.class) +@SuppressWarnings("PMD") +class IbmMqApplicationTests { + + public static MockWebServer mockWebServer; + + private ConnectionDetailsEvent connectionDetailsEvent; + + @BeforeAll + static void setup() throws Exception { + mockWebServer = new MockWebServer(); + mockWebServer.start(); + + } + + @BeforeEach + void init() throws Exception { + String baseurl = String.format("http://localhost:%s", mockWebServer.getPort()); + + connectionDetailsEvent = ConnectionDetailsEvent.builder() + .url(baseurl) + .messagingServiceId("1") + .name("name") + .authenticationDetails(List.of(AuthenticationDetailsEvent.builder() + .credentials(List.of(CredentialDetailsEvent.builder() + .properties(List.of( + EventProperty.builder() + .name("username") + .value("ush") + .build(), + EventProperty.builder() + .name("password") + .value("password") + .build())) + .build())) + .build())) + .build(); + } + + @Test + void testGetQueues() throws Exception { + IbmMqClientManagerImpl client = new IbmMqClientManagerImpl(); + IbmMqHttpClient httpClient = client.getClient(connectionDetailsEvent); + + Path filePath = Paths.get("src/test/resources/queue_response.json"); + String queueJson = Files.readString(filePath); + + mockWebServer.enqueue(new MockResponse() + .setBody(queueJson) + .addHeader("Content-Type", "application/json") + ); + + IbmMqQueueResponse response = httpClient.getQueues(); + + long expected_queue_count = 8; + + Assert.assertEquals("Unexpected number of queues returned.", expected_queue_count, response.getQueue().size()); + Assert.assertEquals("First element does not match expected queue name,", + "SYSTEM.ADMIN.STATISTICS.QUEUE", response.getQueue().get(0).getName()); + } + + @Test + void testGetSubscriptions() throws Exception { + IbmMqClientManagerImpl client = new IbmMqClientManagerImpl(); + IbmMqHttpClient httpClient = client.getClient(connectionDetailsEvent); + + //load our test file + Path filePath = Paths.get("src/test/resources/subscription_response.json"); + String subJson = Files.readString(filePath); + + //add it to our Mock Webserver. + //The server will respond with the contents of the test file + mockWebServer.enqueue(new MockResponse() + .setBody(subJson) + .addHeader("Content-Type", "application/json") + ); + + IbmMqSubscriptionResponse response = httpClient.getSubscriptions(); + + //ensure we received correct data + long expected_topic_count = 15; + + Assert.assertEquals("Unexpected number of queues returned.", expected_topic_count, response.getSubscription().size()); + Assert.assertEquals("First element does not match expected subscription name,", + "$SYS/MQ/INFO/QMGR/QM1/Monitor/CPU/SystemSummary", response.getSubscription().get(0).getResolvedTopicString()); + } + + @AfterAll + static void shutDown() throws Exception { + mockWebServer.shutdown(); + } +} diff --git a/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqTestConfig.java b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqTestConfig.java new file mode 100644 index 00000000..af95986e --- /dev/null +++ b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqTestConfig.java @@ -0,0 +1,40 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq; + +import com.solace.maas.ep.event.management.agent.plugin.processor.ScanTypeDescendentsProcessor; +import com.solace.maas.ep.event.management.agent.plugin.processor.logging.MDCProcessor; +import com.solace.maas.ep.event.management.agent.plugin.route.manager.RouteManager; +import com.solace.maas.ep.event.management.agent.plugin.service.MessagingServiceDelegateService; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +import static org.mockito.Mockito.mock; + +@TestConfiguration +public class IbmMqTestConfig { + + @Bean + @Primary + public MessagingServiceDelegateService messagingServiceDelegateService() { + return mock(MessagingServiceDelegateService.class); + } + + @Bean + @Primary + public MDCProcessor mdcProcessor() { + return mock(MDCProcessor.class); + } + + @Bean + @Primary + public ScanTypeDescendentsProcessor emptyScanEntityProcessor() { + return mock(ScanTypeDescendentsProcessor.class); + } + + @Bean + @Primary + public RouteManager RouteManager() { + return mock(RouteManager.class); + } + +} diff --git a/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImplTests.java b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImplTests.java new file mode 100644 index 00000000..c5bc2cef --- /dev/null +++ b/service/ibmmq-plugin/src/test/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/route/delegate/IbmMqRouteDelegateImplTests.java @@ -0,0 +1,61 @@ +package com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.delegate; + +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.IbmMqTestConfig; +import com.solace.maas.ep.event.management.agent.plugin.ibmmq.route.enumeration.IbmMqScanType; +import com.solace.maas.ep.event.management.agent.plugin.route.RouteBundle; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; + +@ActiveProfiles("TEST") +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = IbmMqTestConfig.class) +public class IbmMqRouteDelegateImplTests { + + @InjectMocks + private IbmMqRouteDelegateImpl ibmMqRouteDelegate; + + private final List destinations = List.of( + RouteBundle.builder() + .destinations(List.of()) + .recipients(List.of()) + .routeId("testRoute") + .firstRouteInChain(false) + .messagingServiceId("service1") + .build()); + + @Test + public void testGenerateIbmMqQueueRouteList() { + List routeBundles = ibmMqRouteDelegate.generateRouteList(destinations, List.of(), + IbmMqScanType.IBMMQ_QUEUE.name(), + "service1"); + + assertThatNoException(); + assertThat(!routeBundles.isEmpty()); + } + + @Test + public void testGenerateIbmMqSubscriptionRouteList() { + List routeBundles = ibmMqRouteDelegate.generateRouteList(destinations, List.of(), + IbmMqScanType.IBMMQ_SUBSCRIPTION.name(), + "service1"); + + assertThatNoException(); + assertThat(!routeBundles.isEmpty()); + } + + @Test + public void testGenerateIbmMqAllRouteList() { + List routeBundles = ibmMqRouteDelegate.generateRouteList(destinations, List.of(), + IbmMqScanType.IBMMQ_ALL.name(), + "service1"); + + assertThatNoException(); + assertThat(!routeBundles.isEmpty()); + } +} diff --git a/service/ibmmq-plugin/src/test/resources/queue_response.json b/service/ibmmq-plugin/src/test/resources/queue_response.json new file mode 100644 index 00000000..f3457189 --- /dev/null +++ b/service/ibmmq-plugin/src/test/resources/queue_response.json @@ -0,0 +1,42 @@ +{ + "queue": [ + { + "name": "SYSTEM.ADMIN.STATISTICS.QUEUE", + "type": "local" + }, + { + "name": "SYSTEM.DEFAULT.INITIATION.QUEUE", + "type": "local" + }, + { + "name": "SYSTEM.ADMIN.ACCOUNTING.QUEUE", + "type": "local" + }, + { + "name": "SYSTEM.ADMIN.LOGGER.EVENT", + "type": "local" + }, + { + "name": "SYSTEM.BROKER.CONTROL.QUEUE", + "type": "local" + }, + { + "name": "SYSTEM.CLUSTER.TRANSMIT.MODEL.QUEUE", + "model": { + "type": "permanentDynamic" + }, + "type": "model" + }, + { + "name": "SYSTEM.ADMIN.TRACE.ROUTE.QUEUE", + "type": "local" + }, + { + "name": "SYSTEM.MQEXPLORER.REPLY.MODEL", + "model": { + "type": "temporaryDynamic" + }, + "type": "model" + } + ] +} \ No newline at end of file diff --git a/service/ibmmq-plugin/src/test/resources/subscription_response.json b/service/ibmmq-plugin/src/test/resources/subscription_response.json new file mode 100644 index 00000000..6a113e30 --- /dev/null +++ b/service/ibmmq-plugin/src/test/resources/subscription_response.json @@ -0,0 +1,79 @@ +{ + "subscription": [ + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/CPU/SystemSummary", + "name": "", + "id": "414D5120514D312020202020202020203C434B6567270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/CPU/QMgrSummary", + "name": "", + "id": "414D5120514D312020202020202020203C434B6569270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/DISK/SystemSummary", + "name": "", + "id": "414D5120514D312020202020202020203C434B656B270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/DISK/QMgrSummary", + "name": "", + "id": "414D5120514D312020202020202020203C434B656D270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/DISK/Log", + "name": "", + "id": "414D5120514D312020202020202020203C434B656F270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/PUBLISH", + "name": "", + "id": "414D5120514D312020202020202020203C434B6571270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/CONNDISC", + "name": "", + "id": "414D5120514D312020202020202020203C434B6573270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/OPENCLOSE", + "name": "", + "id": "414D5120514D312020202020202020203C434B6575270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/INQSET", + "name": "", + "id": "414D5120514D312020202020202020203C434B6577270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/PUT", + "name": "", + "id": "414D5120514D312020202020202020203C434B6579270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/GET", + "name": "", + "id": "414D5120514D312020202020202020203C434B657B270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/SYNCPOINT", + "name": "", + "id": "414D5120514D312020202020202020203C434B657D270040" + }, + { + "resolvedTopicString": "$SYS/MQ/INFO/QMGR/QM1/Monitor/STATMQI/SUBSCRIBE", + "name": "", + "id": "414D5120514D312020202020202020203C434B657F270040" + }, + { + "resolvedTopicString": "", + "name": "SYSTEM.DEFAULT.SUB", + "id": "414D5120514D312020202020202020207964416503010040" + }, + { + "resolvedTopicString": "SYSTEM.BROKER.ADMIN.STREAM/MQ/QM1 /StreamSupport", + "name": "QM1 SYSTEM.BROKER.INTER.BROKER.COMMUNICATIONS 414D51590101000000000000000000000000000000000000 SYSTEM.BROKER.ADMIN.STREAM MQ/QM1 /StreamSupport", + "id": "414D5120514D31202020202020202020B2644165061D0040" + } + ] +} \ No newline at end of file diff --git a/service/pom.xml b/service/pom.xml index 16ad5ff7..5396cc95 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -23,6 +23,7 @@ local-storage-plugin confluent-schema-registry-plugin application + ibmmq-plugin 17 From 6e65a315635d6a4a9991ab424b3f4800650c48d7 Mon Sep 17 00:00:00 2001 From: Ush Shukla <21085773+Ushnash@users.noreply.github.com> Date: Tue, 20 Feb 2024 23:38:01 +0100 Subject: [PATCH 2/5] updating with review suggestions from PR #148 --- README.md | 1 + .../src/main/resources/application.yml | 358 +++++++++--------- service/ibmmq-plugin/pom.xml | 30 +- .../ibmmq/client/http/IbmMqHttpClient.java | 2 +- .../ibmmq/client/http/IbmMqQueueResponse.java | 4 + .../http/IbmMqSubscriptionResponse.java | 4 + .../manager/client/IbmMqClientConfigImpl.java | 6 - .../client/IbmMqClientManagerImpl.java | 19 +- .../ibmmq/processor/IbmMqQueueProcessor.java | 3 +- .../processor/IbmMqSubscriptionProcessor.java | 3 +- .../processor/event/IbmMqQueueEvent.java | 4 + .../event/IbmMqSubscriptionEvent.java | 4 + 12 files changed, 218 insertions(+), 220 deletions(-) diff --git a/README.md b/README.md index 6f2bc597..2b45c2aa 100644 --- a/README.md +++ b/README.md @@ -504,6 +504,7 @@ The Event Management Agent comes with the following event or message broker plug * Solace PubSub+ * Confluent Schema Registry * MSK +* IBM MQ The default application.yml provides various plugin examples. For Kafka, the properties section under credentials is passthrough. For example a property in ConsumerConfig or SSLConfigs classes. diff --git a/service/application/src/main/resources/application.yml b/service/application/src/main/resources/application.yml index c0bba152..aacb0e07 100644 --- a/service/application/src/main/resources/application.yml +++ b/service/application/src/main/resources/application.yml @@ -88,190 +88,164 @@ eventPortal: password: ${EP_GATEWAY_PASSWORD} clientName: runtime_agent_${EP_RUNTIME_AGENT_ID} # 'client_' + runtimeAgentId +# Below is an example of how to set up messaging service configuration in the application.yml file. -plugins: - resources: - # IBMMQ example - - id: ibmmqDefaultService - type: IBMMQ - name: test service - connections: - - name: ibmmqCloudService - url: https://web-qm1-5bc5.qm.us-south.mq.appdomain.cloud/ibmmq/rest/v1/admin/qmgr/QM1 - authentication: - - protocol: BASIC - credentials: - - source: - properties: - - name: username - value: ush - - name: password - value: E5J8yGHjPTErikzOVZ0FiloP47FooNKQSTcTx5jQE-oM - operations: - - name: IBMMQ_QUEUE - # properties: - # - name: msgVpn - # value: ${SOLACE_VPN_NAME} - # - name: sempPageSize - # value: 100 - # Below is an example of how to set up messaging service configuration in the application.yml file. - - #plugins: - # resources: - # # Confluent Schema Registry No Auth example - # - id: someConfluentId - # name: no auth confluent example - # type: confluent_schema_registry - # relatedServices: - # - id1 - # - id2 - # - id3 - # connections: - # - name: myConfluentNoAuth - # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} - # # Confluent Schema Registry Basic Auth example - # - id: someConfluentId - # name: no auth confluent example - # type: confluent_schema_registry - # relatedServices: - # - id1 - # connections: - # - name: myConfluentBasicAuth - # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} - # authentication: - # - protocol: BASIC - # credentials: - # - properties: - # - name: username - # value: ${CONFLUENT_USERNAME} - # - name: password - # value: ${CONFLUENT_PASSWORD} - # source: ENVIRONMENT_VARIABLE - # operations: - # - name: ALL - # # Confluent Schema Registry Basic Auth With SSL example - # - id: someConfluentId - # name: no auth confluent example - # type: confluent_schema_registry - # relatedServices: - # - id1 - # connections: - # - name: myConfluentBasicAuthWithSSL - # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} - # authentication: - # - protocol: BASIC_SSL - # credentials: - # - properties: - # - name: username - # value: ${CONFLUENT_USERNAME} - # - name: password - # value: ${CONFLUENT_PASSWORD} - # - name: ssl.truststore.location - # value: ${TRUSTSTORE_LOCATION} - # - name: ssl.truststore.password - # value: ${TRUSTSTORE_PASSWORD} - # source: ENVIRONMENT_VARIABLE - # operations: - # - name: ALL - # # Confluent Schema Registry Basic Auth With mTLS example - # - id: someConfluentId - # name: Basic Auth With mTLS example - # type: confluent_schema_registry - # relatedServices: - # - id1 - # connections: - # - name: myConfluentBasicAuthWithMTLS - # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} - # authentication: - # - protocol: BASIC_MTLS - # credentials: - # - properties: - # - name: username - # value: ${CONFLUENT_USERNAME} - # - name: password - # value: ${CONFLUENT_PASSWORD} - # - name: ssl.truststore.location - # value: ${TRUSTSTORE_LOCATION} - # - name: ssl.truststore.password - # value: ${TRUSTSTORE_PASSWORD} - # - name: ssl.keystore.location - # value: ${KEYSTORE_LOCATION} - # - name: ssl.keystore.password - # value: ${KEYSTORE_PASSWORD} - # - name: ssl.key.password - # value: ${KEY_PASSWORD} - # source: ENVIRONMENT_VARIABLE - # operations: - # - name: ALL - # # Confluent Schema Registry TLS example - # - id: someConfluentId - # name: no auth confluent example - # type: confluent_schema_registry - # relatedServices: - # - id1 - # connections: - # - name: myConfluentTLS - # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} - # authentication: - # - protocol: TLS - # credentials: - # - properties: - # - name: ssl.truststore.location - # value: ${TRUSTSTORE_LOCATION} - # - name: ssl.truststore.password - # value: ${TRUSTSTORE_PASSWORD} - # source: ENVIRONMENT_VARIABLE - # operations: - # - name: ALL - # # Confluent Schema Registry MTLS example - # - id: someConfluentId - # name: no auth confluent example - # type: confluent_schema_registry - # relatedServices: - # - id1 - # connections: - # - name: myConfluentMTLS - # url: ${CONFLUENT_SCHEMA_REGISTRY_URL} - # authentication: - # - protocol: MTLS - # credentials: - # - properties: - # - name: ssl.truststore.location - # value: ${TRUSTSTORE_LOCATION} - # - name: ssl.truststore.password - # value: ${TRUSTSTORE_PASSWORD} - # - name: ssl.keystore.password - # value: ${KEYSTORE_PASSWORD} - # - name: ssl.keystore.location - # value: ${KEYSTORE_LOCATION} - # - name: ssl.key.password - # value: ${KEY_PASSWORD} - # source: ENVIRONMENT_VARIABLE - # operations: - # - name: ALL - # Solace example - - id: solaceDefaultService - type: SOLACE - name: staging service - connections: - - name: mySolaceServiceSemp - url: ${SOLACE_SEMP_URL} - authentication: - - protocol: SEMP - credentials: - - source: ENVIRONMENT_VARIABLE - operations: - - name: ALL - properties: - - name: username - value: ${SOLACE_SEMP_USERNAME} - - name: password - value: ${SOLACE_SEMP_PASSWORD} - properties: - - name: msgVpn - value: ${SOLACE_VPN_NAME} - - name: sempPageSize - value: 100 +#plugins: +# resources: +# # Confluent Schema Registry No Auth example +# - id: someConfluentId +# name: no auth confluent example +# type: confluent_schema_registry +# relatedServices: +# - id1 +# - id2 +# - id3 +# connections: +# - name: myConfluentNoAuth +# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} +# # Confluent Schema Registry Basic Auth example +# - id: someConfluentId +# name: no auth confluent example +# type: confluent_schema_registry +# relatedServices: +# - id1 +# connections: +# - name: myConfluentBasicAuth +# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} +# authentication: +# - protocol: BASIC +# credentials: +# - properties: +# - name: username +# value: ${CONFLUENT_USERNAME} +# - name: password +# value: ${CONFLUENT_PASSWORD} +# source: ENVIRONMENT_VARIABLE +# operations: +# - name: ALL +# # Confluent Schema Registry Basic Auth With SSL example +# - id: someConfluentId +# name: no auth confluent example +# type: confluent_schema_registry +# relatedServices: +# - id1 +# connections: +# - name: myConfluentBasicAuthWithSSL +# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} +# authentication: +# - protocol: BASIC_SSL +# credentials: +# - properties: +# - name: username +# value: ${CONFLUENT_USERNAME} +# - name: password +# value: ${CONFLUENT_PASSWORD} +# - name: ssl.truststore.location +# value: ${TRUSTSTORE_LOCATION} +# - name: ssl.truststore.password +# value: ${TRUSTSTORE_PASSWORD} +# source: ENVIRONMENT_VARIABLE +# operations: +# - name: ALL +# # Confluent Schema Registry Basic Auth With mTLS example +# - id: someConfluentId +# name: Basic Auth With mTLS example +# type: confluent_schema_registry +# relatedServices: +# - id1 +# connections: +# - name: myConfluentBasicAuthWithMTLS +# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} +# authentication: +# - protocol: BASIC_MTLS +# credentials: +# - properties: +# - name: username +# value: ${CONFLUENT_USERNAME} +# - name: password +# value: ${CONFLUENT_PASSWORD} +# - name: ssl.truststore.location +# value: ${TRUSTSTORE_LOCATION} +# - name: ssl.truststore.password +# value: ${TRUSTSTORE_PASSWORD} +# - name: ssl.keystore.location +# value: ${KEYSTORE_LOCATION} +# - name: ssl.keystore.password +# value: ${KEYSTORE_PASSWORD} +# - name: ssl.key.password +# value: ${KEY_PASSWORD} +# source: ENVIRONMENT_VARIABLE +# operations: +# - name: ALL +# # Confluent Schema Registry TLS example +# - id: someConfluentId +# name: no auth confluent example +# type: confluent_schema_registry +# relatedServices: +# - id1 +# connections: +# - name: myConfluentTLS +# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} +# authentication: +# - protocol: TLS +# credentials: +# - properties: +# - name: ssl.truststore.location +# value: ${TRUSTSTORE_LOCATION} +# - name: ssl.truststore.password +# value: ${TRUSTSTORE_PASSWORD} +# source: ENVIRONMENT_VARIABLE +# operations: +# - name: ALL +# # Confluent Schema Registry MTLS example +# - id: someConfluentId +# name: no auth confluent example +# type: confluent_schema_registry +# relatedServices: +# - id1 +# connections: +# - name: myConfluentMTLS +# url: ${CONFLUENT_SCHEMA_REGISTRY_URL} +# authentication: +# - protocol: MTLS +# credentials: +# - properties: +# - name: ssl.truststore.location +# value: ${TRUSTSTORE_LOCATION} +# - name: ssl.truststore.password +# value: ${TRUSTSTORE_PASSWORD} +# - name: ssl.keystore.password +# value: ${KEYSTORE_PASSWORD} +# - name: ssl.keystore.location +# value: ${KEYSTORE_LOCATION} +# - name: ssl.key.password +# value: ${KEY_PASSWORD} +# source: ENVIRONMENT_VARIABLE +# operations: +# - name: ALL +# # Solace example +# - id: solaceDefaultService +# type: SOLACE +# name: staging service +# connections: +# - name: mySolaceServiceSemp +# url: ${SOLACE_SEMP_URL} +# authentication: +# - protocol: SEMP +# credentials: +# - source: ENVIRONMENT_VARIABLE +# operations: +# - name: ALL +# properties: +# - name: username +# value: ${SOLACE_SEMP_USERNAME} +# - name: password +# value: ${SOLACE_SEMP_PASSWORD} +# properties: +# - name: msgVpn +# value: ${SOLACE_VPN_NAME} +# - name: sempPageSize +# value: 100 # # MTLS example # - id: kafkaMTLSServiceExample # name: mtls kafka cluster example @@ -381,3 +355,21 @@ plugins: # value: software.amazon.msk.auth.iam.IAMLoginModule required; # - name: sasl.client.callback.handler.class # value: software.amazon.msk.auth.iam.IAMClientCallbackHandler +# # IBM MQ Example +# - id: ibmmqDefaultService +# type: IBMMQ +# name: IBM MQ Test Service +# connections: +# - name: IBMMQBroker +# url: ${ADMINISTRATOR_REST_ENDPOINT_URL} +# authentication: +# - protocol: BASIC +# credentials: +# - source: ENVIRONMENT_VARIABLE +# properties: +# - name: username +# value: ${IBMMQ_ADMINISTRATOR_USERNAME} +# - name: password +# value: ${IBMMQ_ADMINISTRATOR_PASSWORD} +# operations: +# - name: IBMMQ_ALL \ No newline at end of file diff --git a/service/ibmmq-plugin/pom.xml b/service/ibmmq-plugin/pom.xml index 1c2bd01f..c842d5eb 100644 --- a/service/ibmmq-plugin/pom.xml +++ b/service/ibmmq-plugin/pom.xml @@ -3,20 +3,18 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - com.solace.maas - maas-event-management-agent-parent - 1.3.2-SNAPSHOT - - ibmmq-plugin - 0.0.2-SNAPSHOT - Solace Event Management Agent - IBMMQ Plugin - Solace Event Management Agent - IBMMQ Plugin + 1.6.1-SNAPSHOT + Solace Event Management Agent - IBM MQ Plugin + Solace Event Management Agent - IBM MQ Plugin - ${java.version} - ${java.version} + 17 + 17 + 1.6.1-SNAPSHOT + 4.1.0 + 13.0 + 4.0.1 UTF-8 @@ -28,17 +26,17 @@ org.springframework.cloud spring-cloud-starter-openfeign - 4.0.4 + ${spring.cloud.openfeign.version} io.github.openfeign feign-jackson - 13.0 + ${openfeign.jackson.version} com.solace.maas plugin - 1.3.2-SNAPSHOT + ${solace.maas.ema.version} org.apache.camel @@ -55,13 +53,13 @@ com.squareup.okhttp3 okhttp - 4.0.1 + ${okhttp.version} test com.squareup.okhttp3 mockwebserver - 4.0.1 + ${okhttp.version} test diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java index 292bf8c2..6d535509 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java @@ -4,7 +4,7 @@ import org.springframework.web.bind.annotation.GetMapping; /** - * Uses OpenFeign to create the MQ REST API Admin Client. + * Interface for OpenFeign to create the IBM MQ REST API Admin Client. */ @FeignClient(name = "ibmmq-http-client") public interface IbmMqHttpClient { diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqQueueResponse.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqQueueResponse.java index 1d6f7da3..d27b6a2a 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqQueueResponse.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqQueueResponse.java @@ -5,6 +5,10 @@ import java.util.List; +/** + * Represents the response JSON from the IBM MQ Admin client + * when querying for Queue information. + */ @Getter public class IbmMqQueueResponse { diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqSubscriptionResponse.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqSubscriptionResponse.java index bb54df2f..e64b6d3c 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqSubscriptionResponse.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqSubscriptionResponse.java @@ -5,6 +5,10 @@ import java.util.List; +/** + * Represents the response JSON from the IBM MQ Admin client + * when querying for Subscription (topic) information. + */ @Data public class IbmMqSubscriptionResponse { diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java index e710520a..8eb4460a 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java @@ -1,14 +1,8 @@ -/** - * - */ package com.solace.maas.ep.event.management.agent.plugin.ibmmq.manager.client; import com.solace.maas.ep.event.management.agent.plugin.manager.client.MessagingServiceClientConfig; import org.springframework.context.annotation.Configuration; -/** - * - */ @Configuration public class IbmMqClientConfigImpl extends MessagingServiceClientConfig { diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java index 15bfb4e9..9bce9d01 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java @@ -1,6 +1,3 @@ -/** - * - */ package com.solace.maas.ep.event.management.agent.plugin.ibmmq.manager.client; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -22,7 +19,9 @@ import java.util.NoSuchElementException; /** - * + * Implementation of the IBM MQ Administration client. + *

+ * This client provides access to the various administrative endpoints exposed by IBM MQ. */ @Slf4j @Data @@ -35,9 +34,10 @@ public IbmMqClientManagerImpl() { @Override public IbmMqHttpClient getClient(ConnectionDetailsEvent connectionDetailsEvent) { - log.trace("Creating IBMMQ-HTTP client for messaging service [{}].", + log.trace("Creating IBM MQ RESTful client for event broker [{}].", connectionDetailsEvent.getMessagingServiceId()); + //get authentication details from config file AuthenticationDetailsEvent authenticationDetailsEvent = connectionDetailsEvent.getAuthenticationDetails() .stream() .findFirst().orElseThrow(() -> { @@ -51,20 +51,19 @@ public IbmMqHttpClient getClient(ConnectionDetailsEvent connectionDetailsEvent) String password = MessagingServiceConfigurationUtil.getPassword(authenticationDetailsEvent); String url = connectionDetailsEvent.getUrl(); - //so that we can configure Jackson + /*so that we can configure Jackson to ignore unknown properties in the + response json. + */ ObjectMapper mapper = JsonMapper .builder() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .build(); - - IbmMqHttpClient client = Feign.builder() + return Feign.builder() .requestInterceptor(new BasicAuthRequestInterceptor(username, password)) .contract(new SpringMvcContract()) .decoder(new JacksonDecoder(mapper)) .target(IbmMqHttpClient.class, url); - - return client; } } diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqQueueProcessor.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqQueueProcessor.java index c580df25..d582da5c 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqQueueProcessor.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqQueueProcessor.java @@ -22,7 +22,6 @@ public class IbmMqQueueProcessor extends ResultProcessorImpl handleEvent(Map properties, Void bo IbmMqHttpClient client = messagingServiceDelegateService.getMessagingServiceClient(messagingServiceId); - log.info("### Invoking Queue endpoint for messaging service with ID {}", messagingServiceId); + log.info("### Invoking Queue endpoint for broker with ID {}", messagingServiceId); IbmMqQueueResponse queueList = client.getQueues(); return queueList.getQueue(); diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqSubscriptionProcessor.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqSubscriptionProcessor.java index e953e4da..61520a2e 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqSubscriptionProcessor.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/IbmMqSubscriptionProcessor.java @@ -22,7 +22,6 @@ public class IbmMqSubscriptionProcessor extends ResultProcessorImpl handleEvent(Map properties, IbmMqHttpClient client = messagingServiceDelegateService.getMessagingServiceClient(messagingServiceId); - log.info("### Invoking Queue endpoint for messaging service with ID {}", messagingServiceId); + log.info("### Invoking Queue endpoint for broker with ID {}", messagingServiceId); IbmMqSubscriptionResponse subscriptionList = client.getSubscriptions(); return subscriptionList.getSubscription(); diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqQueueEvent.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqQueueEvent.java index 08b50a82..f9ad31ac 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqQueueEvent.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqQueueEvent.java @@ -4,6 +4,10 @@ import java.io.Serializable; +/** + * Attributes parsed from the response JSON. + * Note: Other attributes may be returned in the raw JSON. + */ @Getter public class IbmMqQueueEvent implements Serializable { diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqSubscriptionEvent.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqSubscriptionEvent.java index 0067feb0..df9d5e65 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqSubscriptionEvent.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/processor/event/IbmMqSubscriptionEvent.java @@ -4,6 +4,10 @@ import java.io.Serializable; +/** + * Attributes parsed from the response JSON. + * Note: Other attributes may be returned in the raw JSON. + */ @Data public class IbmMqSubscriptionEvent implements Serializable { From 696d92d01cee9480dec65eeaa6672aef5610ee7b Mon Sep 17 00:00:00 2001 From: Ush Shukla <21085773+Ushnash@users.noreply.github.com> Date: Wed, 21 Feb 2024 23:06:33 +0100 Subject: [PATCH 3/5] updating/adding version numbers --- service/application/pom.xml | 4 ++-- service/ibmmq-plugin/pom.xml | 5 +++++ service/pom.xml | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/service/application/pom.xml b/service/application/pom.xml index 8fa53d15..b9a370a8 100644 --- a/service/application/pom.xml +++ b/service/application/pom.xml @@ -248,9 +248,9 @@ 1.6.1-SNAPSHOT - com.solace.maas + com.solace.maas.plugin.ibmmq ibmmq-plugin - 0.0.2-SNAPSHOT + 1.6.1-SNAPSHOT diff --git a/service/ibmmq-plugin/pom.xml b/service/ibmmq-plugin/pom.xml index c842d5eb..124676e2 100644 --- a/service/ibmmq-plugin/pom.xml +++ b/service/ibmmq-plugin/pom.xml @@ -3,6 +3,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + com.solace.maas.plugin.ibmmq ibmmq-plugin 1.6.1-SNAPSHOT Solace Event Management Agent - IBM MQ Plugin @@ -12,9 +13,11 @@ 17 17 1.6.1-SNAPSHOT + 3.1.7 4.1.0 13.0 4.0.1 + 4.2.0 UTF-8 @@ -22,6 +25,7 @@ org.springframework.boot spring-boot-starter + ${spring.boot.version} org.springframework.cloud @@ -48,6 +52,7 @@ org.springframework.boot spring-boot-starter-test + ${spring.boot.version} test diff --git a/service/pom.xml b/service/pom.xml index fd45818e..054ea383 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -21,8 +21,8 @@ terraform-plugin local-storage-plugin confluent-schema-registry-plugin - application ibmmq-plugin + application 17 From dbebe9673255c2cd386eb633d77bf830e8e35bae Mon Sep 17 00:00:00 2001 From: Ush Shukla <21085773+Ushnash@users.noreply.github.com> Date: Thu, 7 Mar 2024 23:09:02 -0600 Subject: [PATCH 4/5] Replaced OpenFeign with Spring-native HTTPInterface for declarative REST client. Also, updated version to match parent. --- service/ibmmq-plugin/pom.xml | 46 ++++++++++++------- .../agent/plugin/ibmmq/IbmMqApplication.java | 2 - .../ibmmq/client/http/IbmMqHttpClient.java | 12 ++--- .../manager/client/IbmMqClientConfigImpl.java | 4 +- .../client/IbmMqClientManagerImpl.java | 32 ++++++------- 5 files changed, 51 insertions(+), 45 deletions(-) diff --git a/service/ibmmq-plugin/pom.xml b/service/ibmmq-plugin/pom.xml index 124676e2..6a194e1f 100644 --- a/service/ibmmq-plugin/pom.xml +++ b/service/ibmmq-plugin/pom.xml @@ -5,38 +5,51 @@ 4.0.0 com.solace.maas.plugin.ibmmq ibmmq-plugin - 1.6.1-SNAPSHOT + 1.6.3-SNAPSHOT Solace Event Management Agent - IBM MQ Plugin Solace Event Management Agent - IBM MQ Plugin 17 17 - 1.6.1-SNAPSHOT - 3.1.7 - 4.1.0 - 13.0 + 1.6.3-SNAPSHOT + 3.1.8 + 4.0.1 4.2.0 UTF-8 + org.springframework.boot - spring-boot-starter + spring-boot-starter-webflux ${spring.boot.version} + + + ch.qos.logback + logback-classic + + - - org.springframework.cloud - spring-cloud-starter-openfeign - ${spring.cloud.openfeign.version} - - - io.github.openfeign - feign-jackson - ${openfeign.jackson.version} - + com.solace.maas plugin @@ -74,6 +87,7 @@ org.springframework.boot spring-boot-maven-plugin + ${spring.boot.version} diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplication.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplication.java index 5ae4c5b1..74c50b23 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplication.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/IbmMqApplication.java @@ -2,10 +2,8 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication -@EnableFeignClients public class IbmMqApplication { public static void main(String[] args) { diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java index 6d535509..c4b77816 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/client/http/IbmMqHttpClient.java @@ -1,19 +1,19 @@ package com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http; -import org.springframework.cloud.openfeign.FeignClient; -import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.service.annotation.GetExchange; +import org.springframework.web.service.annotation.HttpExchange; /** - * Interface for OpenFeign to create the IBM MQ REST API Admin Client. + * Interface for Spring HTTPInterface to create the IBM MQ Admin Client. */ -@FeignClient(name = "ibmmq-http-client") +@HttpExchange public interface IbmMqHttpClient { /*Gets all queues on a given queue manager*/ - @GetMapping("/queue") + @GetExchange("/queue") IbmMqQueueResponse getQueues(); /*Gets all subscriptions (topics) on a given queue manager*/ - @GetMapping("/subscription") + @GetExchange("/subscription") IbmMqSubscriptionResponse getSubscriptions(); } diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java index 8eb4460a..72eb071b 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientConfigImpl.java @@ -6,10 +6,8 @@ @Configuration public class IbmMqClientConfigImpl extends MessagingServiceClientConfig { - private static final String SERVICE_NAME = "IBMMQ"; - protected IbmMqClientConfigImpl() { - super(SERVICE_NAME, new IbmMqClientManagerImpl()); + super("IBMMQ", new IbmMqClientManagerImpl()); } } diff --git a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java index 9bce9d01..523c5075 100644 --- a/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java +++ b/service/ibmmq-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/ibmmq/manager/client/IbmMqClientManagerImpl.java @@ -1,20 +1,17 @@ package com.solace.maas.ep.event.management.agent.plugin.ibmmq.manager.client; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.json.JsonMapper; import com.solace.maas.ep.event.management.agent.plugin.ibmmq.client.http.IbmMqHttpClient; import com.solace.maas.ep.event.management.agent.plugin.manager.client.MessagingServiceClientManager; import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.AuthenticationDetailsEvent; import com.solace.maas.ep.event.management.agent.plugin.messagingService.event.ConnectionDetailsEvent; import com.solace.maas.ep.event.management.agent.plugin.util.MessagingServiceConfigurationUtil; -import feign.Feign; -import feign.auth.BasicAuthRequestInterceptor; -import feign.jackson.JacksonDecoder; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.springframework.cloud.openfeign.support.SpringMvcContract; import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.ExchangeFilterFunctions; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.support.WebClientAdapter; +import org.springframework.web.service.invoker.HttpServiceProxyFactory; import java.util.NoSuchElementException; @@ -47,23 +44,22 @@ public IbmMqHttpClient getClient(ConnectionDetailsEvent connectionDetailsEvent) return new NoSuchElementException(message); }); + //grab authentication details String username = MessagingServiceConfigurationUtil.getUsername(authenticationDetailsEvent); String password = MessagingServiceConfigurationUtil.getPassword(authenticationDetailsEvent); String url = connectionDetailsEvent.getUrl(); - /*so that we can configure Jackson to ignore unknown properties in the - response json. - */ - ObjectMapper mapper = JsonMapper - .builder() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + //setup a basic webclient that will be used in generating + //the actual IBM HTTP Client + WebClient client = WebClient.builder() + .filter(ExchangeFilterFunctions.basicAuthentication(username, password)) + .baseUrl(url) .build(); - return Feign.builder() - .requestInterceptor(new BasicAuthRequestInterceptor(username, password)) - .contract(new SpringMvcContract()) - .decoder(new JacksonDecoder(mapper)) - .target(IbmMqHttpClient.class, url); + HttpServiceProxyFactory proxyFactory = HttpServiceProxyFactory + .builder(WebClientAdapter.forClient(client)).build(); + + return proxyFactory.createClient(IbmMqHttpClient.class); } } From 635e70d721b3f77dec858f915a3c0ec57a505019 Mon Sep 17 00:00:00 2001 From: hankspencer Date: Tue, 7 May 2024 11:36:37 -0400 Subject: [PATCH 5/5] merge with upstream and update ibm mq documentation --- service/application/pom.xml | 2 +- .../src/main/resources/application.yml | 35 ++++++++++--------- service/ibmmq-plugin/pom.xml | 6 ++-- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/service/application/pom.xml b/service/application/pom.xml index 7dfe3fee..edc996ba 100644 --- a/service/application/pom.xml +++ b/service/application/pom.xml @@ -250,7 +250,7 @@ com.solace.maas.plugin.ibmmq ibmmq-plugin - 1.6.1-SNAPSHOT + 1.6.6-SNAPSHOT diff --git a/service/application/src/main/resources/application.yml b/service/application/src/main/resources/application.yml index aacb0e07..1a645acc 100644 --- a/service/application/src/main/resources/application.yml +++ b/service/application/src/main/resources/application.yml @@ -356,20 +356,21 @@ eventPortal: # - name: sasl.client.callback.handler.class # value: software.amazon.msk.auth.iam.IAMClientCallbackHandler # # IBM MQ Example -# - id: ibmmqDefaultService -# type: IBMMQ -# name: IBM MQ Test Service -# connections: -# - name: IBMMQBroker -# url: ${ADMINISTRATOR_REST_ENDPOINT_URL} -# authentication: -# - protocol: BASIC -# credentials: -# - source: ENVIRONMENT_VARIABLE -# properties: -# - name: username -# value: ${IBMMQ_ADMINISTRATOR_USERNAME} -# - name: password -# value: ${IBMMQ_ADMINISTRATOR_PASSWORD} -# operations: -# - name: IBMMQ_ALL \ No newline at end of file +# - id: ibmmqDefaultService +# type: IBMMQ +# name: IBM MQ Test Service +# connections: +# - name: IBMMQBroker +## Example: https://[domain:[port]]/ibmmq/rest/v1/admin/qmgr/{qmgrName} +# url: ${IBM_MQ_REST_API_URL} +# authentication: +# - protocol: BASIC +# credentials: +# - source: ENVIRONMENT_VARIABLE +# operations: +# - name: IBMMQ_ALL +# properties: +# - name: username +# value: ${IBMMQ_ADMINISTRATOR_USERNAME} +# - name: password +# value: ${IBMMQ_ADMINISTRATOR_PASSWORD} diff --git a/service/ibmmq-plugin/pom.xml b/service/ibmmq-plugin/pom.xml index 6a194e1f..05ca5954 100644 --- a/service/ibmmq-plugin/pom.xml +++ b/service/ibmmq-plugin/pom.xml @@ -5,15 +5,15 @@ 4.0.0 com.solace.maas.plugin.ibmmq ibmmq-plugin - 1.6.3-SNAPSHOT + 1.6.6-SNAPSHOT Solace Event Management Agent - IBM MQ Plugin Solace Event Management Agent - IBM MQ Plugin 17 17 - 1.6.3-SNAPSHOT - 3.1.8 + 1.6.6-SNAPSHOT + 3.1.11