From 0f225d86c1663c718e6e6fa0f5c35fe2b1233352 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Wed, 16 Apr 2025 12:18:44 -0400 Subject: [PATCH] Revert "GH-9441: Deprecate Hazelcast module" This reverts commit 96ddc019 --- .../integration/hazelcast/CacheEventType.java | 3 +- .../hazelcast/CacheListeningPolicyType.java | 3 +- .../hazelcast/ClusterMonitorType.java | 3 +- .../DistributedSQLIterationType.java | 3 +- .../hazelcast/HazelcastHeaders.java | 3 +- ...zelcastIntegrationDefinitionValidator.java | 4 +- .../HazelcastLocalInstanceRegistrar.java | 4 +- ...stIntegrationConfigurationInitializer.java | 4 +- ...terMonitorInboundChannelAdapterParser.java | 4 +- ...nuousQueryInboundChannelAdapterParser.java | 4 +- ...ributedSQLInboundChannelAdapterParser.java | 4 +- ...ventDrivenInboundChannelAdapterParser.java | 4 +- .../HazelcastIntegrationNamespaceHandler.java | 4 +- ...HazelcastOutboundChannelAdapterParser.java | 4 +- .../AbstractHazelcastMessageProducer.java | 4 +- ...azelcastClusterMonitorMessageProducer.java | 4 +- ...zelcastContinuousQueryMessageProducer.java | 4 +- .../HazelcastDistributedSQLMessageSource.java | 5 +- .../HazelcastEventDrivenMessageProducer.java | 4 +- .../hazelcast/leader/LeaderInitiator.java | 3 +- .../listener/HazelcastMembershipListener.java | 4 +- .../hazelcast/lock/HazelcastLockRegistry.java | 3 +- .../message/EntryEventMessagePayload.java | 3 +- .../metadata/HazelcastMetadataStore.java | 3 +- .../HazelcastCacheWritingMessageHandler.java | 4 +- .../store/HazelcastMessageStore.java | 3 +- ...rationDefinitionValidatorTests-context.xml | 19 + ...stIntegrationDefinitionValidatorTests.java | 128 +++++ .../HazelcastIntegrationTestUser.java | 116 +++++ .../HazelcastTestRequestHandlerAdvice.java | 50 ++ .../IdempotentReceiverIntegrationTests.java | 372 ++++++++++++++ .../integration/hazelcast/common-config.xml | 18 + ...dMapInboundChannelAdapterTests-context.xml | 71 +++ ...tributedMapInboundChannelAdapterTests.java | 157 ++++++ ...itorInboundChannelAdapterTests-context.xml | 170 +++++++ ...sterMonitorInboundChannelAdapterTests.java | 111 +++++ ...ivenInboundChannelAdapterTests-context.xml | 46 ++ ...EventDrivenInboundChannelAdapterTests.java | 100 ++++ ...ivenInboundChannelAdapterTests-context.xml | 56 +++ ...EventDrivenInboundChannelAdapterTests.java | 144 ++++++ ...ivenInboundChannelAdapterTests-context.xml | 47 ++ ...EventDrivenInboundChannelAdapterTests.java | 105 ++++ ...dSQLInboundChannelAdapterTests-context.xml | 67 +++ ...tributedSQLInboundChannelAdapterTests.java | 90 ++++ ...ivenInboundChannelAdapterTests-context.xml | 44 ++ ...EventDrivenInboundChannelAdapterTests.java | 105 ++++ ...ivenInboundChannelAdapterTests-context.xml | 25 + ...EventDrivenInboundChannelAdapterTests.java | 54 ++ ...ivenInboundChannelAdapterTests-context.xml | 44 ++ ...EventDrivenInboundChannelAdapterTests.java | 125 +++++ ...ivenInboundChannelAdapterTests-context.xml | 55 ++ ...EventDrivenInboundChannelAdapterTests.java | 161 ++++++ ...edMapInboundChannelAdapterConfigTests.java | 84 ++++ ...nitorInboundChannelAdapterConfigTests.java | 58 +++ ...edSQLInboundChannelAdapterConfigTests.java | 96 ++++ ...rivenInboundChannelAdapterConfigTests.java | 153 ++++++ ...stIntegrationInboundTestConfiguration.java | 394 +++++++++++++++ ...zelcastInboundChannelAdapterTestUtils.java | 370 ++++++++++++++ .../leader/LeaderInitiatorTests.java | 356 +++++++++++++ .../lock/HazelcastLockRegistryTests.java | 284 +++++++++++ .../metadata/HazelcastMetadataStoreTests.java | 163 ++++++ ...astOutboundChannelAdapterTests-context.xml | 280 +++++++++++ .../HazelcastOutboundChannelAdapterTests.java | 471 ++++++++++++++++++ ...tIntegrationOutboundTestConfiguration.java | 298 +++++++++++ ...castOutboundChannelAdapterConfigTests.java | 200 ++++++++ ...elcastOutboundChannelAdapterTestUtils.java | 248 +++++++++ .../store/HazelcastMessageStoreTests.java | 176 +++++++ .../src/test/resources/log4j2-test.xml | 16 + .../antora/modules/ROOT/pages/hazelcast.adoc | 3 - 69 files changed, 6154 insertions(+), 71 deletions(-) create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidatorTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidatorTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationTestUser.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastTestRequestHandlerAdvice.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/IdempotentReceiverIntegrationTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/common-config.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastCQDistributedMapInboundChannelAdapterTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastCQDistributedMapInboundChannelAdapterTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorInboundChannelAdapterTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorInboundChannelAdapterTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedListEventDrivenInboundChannelAdapterTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedListEventDrivenInboundChannelAdapterTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedMapEventDrivenInboundChannelAdapterTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedMapEventDrivenInboundChannelAdapterTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedQueueEventDrivenInboundChannelAdapterTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedQueueEventDrivenInboundChannelAdapterTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLInboundChannelAdapterTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLInboundChannelAdapterTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSetEventDrivenInboundChannelAdapterTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSetEventDrivenInboundChannelAdapterTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedTopicEventDrivenInboundChannelAdapterTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedTopicEventDrivenInboundChannelAdapterTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastMultiMapEventDrivenInboundChannelAdapterTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastMultiMapEventDrivenInboundChannelAdapterTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastReplicatedMapEventDrivenInboundChannelAdapterTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastReplicatedMapEventDrivenInboundChannelAdapterTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastCQDistributedMapInboundChannelAdapterConfigTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastClusterMonitorInboundChannelAdapterConfigTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastDistributedSQLInboundChannelAdapterConfigTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastEventDrivenInboundChannelAdapterConfigTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastIntegrationInboundTestConfiguration.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/util/HazelcastInboundChannelAdapterTestUtils.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/leader/LeaderInitiatorTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/lock/HazelcastLockRegistryTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/metadata/HazelcastMetadataStoreTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/HazelcastOutboundChannelAdapterTests-context.xml create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/HazelcastOutboundChannelAdapterTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/config/HazelcastIntegrationOutboundTestConfiguration.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/config/HazelcastOutboundChannelAdapterConfigTests.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/util/HazelcastOutboundChannelAdapterTestUtils.java create mode 100644 spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/store/HazelcastMessageStoreTests.java create mode 100644 spring-integration-hazelcast/src/test/resources/log4j2-test.xml diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/CacheEventType.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/CacheEventType.java index f4e27e2e9a..455d4def81 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/CacheEventType.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/CacheEventType.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,6 @@ package org.springframework.integration.hazelcast; * * @see org.springframework.integration.hazelcast.inbound.AbstractHazelcastMessageProducer */ -@Deprecated(forRemoval = true, since = "6.5") public enum CacheEventType { /** diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/CacheListeningPolicyType.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/CacheListeningPolicyType.java index 81aec0db62..5eeceab504 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/CacheListeningPolicyType.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/CacheListeningPolicyType.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,6 @@ package org.springframework.integration.hazelcast; * * @see org.springframework.integration.hazelcast.inbound.AbstractHazelcastMessageProducer */ -@Deprecated(forRemoval = true, since = "6.5") public enum CacheListeningPolicyType { /** diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/ClusterMonitorType.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/ClusterMonitorType.java index 442ecb58fc..aac0910a9b 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/ClusterMonitorType.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/ClusterMonitorType.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,6 @@ package org.springframework.integration.hazelcast; * @see com.hazelcast.core.DistributedObjectListener * @see com.hazelcast.core.LifecycleListener */ -@Deprecated(forRemoval = true, since = "6.5") public enum ClusterMonitorType { /** diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/DistributedSQLIterationType.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/DistributedSQLIterationType.java index 702cd5b6dc..ca3a99bc3d 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/DistributedSQLIterationType.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/DistributedSQLIterationType.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,6 @@ package org.springframework.integration.hazelcast; * @see org.springframework.integration.hazelcast.inbound.HazelcastDistributedSQLMessageSource * @see com.hazelcast.map.IMap */ -@Deprecated(forRemoval = true, since = "6.5") public enum DistributedSQLIterationType { /** diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastHeaders.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastHeaders.java index eb2af46964..6fedd518dc 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastHeaders.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastHeaders.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,6 @@ package org.springframework.integration.hazelcast; * * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") public abstract class HazelcastHeaders { private static final String PREFIX = "hazelcast_"; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidator.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidator.java index 872ab3038a..014926aaed 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidator.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidator.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,8 +40,6 @@ import org.springframework.util.StringUtils; * * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public final class HazelcastIntegrationDefinitionValidator { public static > Set validateEnumType(final Class enumType, final String types) { diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastLocalInstanceRegistrar.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastLocalInstanceRegistrar.java index 1083e15959..d541c3f06d 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastLocalInstanceRegistrar.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/HazelcastLocalInstanceRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,8 +40,6 @@ import org.springframework.integration.hazelcast.listener.HazelcastMembershipLis * * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastLocalInstanceRegistrar implements SmartInitializingSingleton { private static final Log logger = LogFactory.getLog(HazelcastLocalInstanceRegistrar.class); diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/HazelcastIntegrationConfigurationInitializer.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/HazelcastIntegrationConfigurationInitializer.java index 465919f013..db0bfb6772 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/HazelcastIntegrationConfigurationInitializer.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/HazelcastIntegrationConfigurationInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,8 +31,6 @@ import org.springframework.integration.hazelcast.HazelcastLocalInstanceRegistrar * * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastIntegrationConfigurationInitializer implements IntegrationConfigurationInitializer { @Override diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastClusterMonitorInboundChannelAdapterParser.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastClusterMonitorInboundChannelAdapterParser.java index 9882eb70a4..120c9c269b 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastClusterMonitorInboundChannelAdapterParser.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastClusterMonitorInboundChannelAdapterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,8 +34,6 @@ import org.springframework.util.StringUtils; * @author Eren Avsarogullari * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastClusterMonitorInboundChannelAdapterParser extends AbstractSingleBeanDefinitionParser { diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastContinuousQueryInboundChannelAdapterParser.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastContinuousQueryInboundChannelAdapterParser.java index 50dc3a63d4..19a0f16740 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastContinuousQueryInboundChannelAdapterParser.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastContinuousQueryInboundChannelAdapterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,8 +37,6 @@ import org.springframework.util.StringUtils; * * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastContinuousQueryInboundChannelAdapterParser extends AbstractSingleBeanDefinitionParser { private static final String CHANNEL_ATTRIBUTE = "channel"; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastDistributedSQLInboundChannelAdapterParser.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastDistributedSQLInboundChannelAdapterParser.java index 8ed184d001..2906e0e8a2 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastDistributedSQLInboundChannelAdapterParser.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastDistributedSQLInboundChannelAdapterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,8 +33,6 @@ import org.springframework.util.StringUtils; * @author Eren Avsarogullari * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastDistributedSQLInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser { private static final String CACHE_ATTRIBUTE = "cache"; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastEventDrivenInboundChannelAdapterParser.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastEventDrivenInboundChannelAdapterParser.java index dd3f6042ba..bbc23cb0f1 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastEventDrivenInboundChannelAdapterParser.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastEventDrivenInboundChannelAdapterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,8 +35,6 @@ import org.springframework.util.StringUtils; * @author Eren Avsarogullari * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastEventDrivenInboundChannelAdapterParser extends AbstractSingleBeanDefinitionParser { private static final String CHANNEL_ATTRIBUTE = "channel"; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastIntegrationNamespaceHandler.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastIntegrationNamespaceHandler.java index e8600c238d..085c2f3f2c 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastIntegrationNamespaceHandler.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastIntegrationNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,8 +24,6 @@ import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHa * @author Eren Avsarogullari * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastIntegrationNamespaceHandler extends AbstractIntegrationNamespaceHandler { @Override diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastOutboundChannelAdapterParser.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastOutboundChannelAdapterParser.java index efd0f559df..5bd0d41d64 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastOutboundChannelAdapterParser.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/config/xml/HazelcastOutboundChannelAdapterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,8 +33,6 @@ import org.springframework.integration.hazelcast.outbound.HazelcastCacheWritingM * @author Eren Avsarogullari * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser { private static final String CACHE_ATTRIBUTE = "cache"; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/AbstractHazelcastMessageProducer.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/AbstractHazelcastMessageProducer.java index b5c3c12b6d..a3c295bf4e 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/AbstractHazelcastMessageProducer.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/AbstractHazelcastMessageProducer.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,8 +54,6 @@ import org.springframework.util.Assert; * * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public abstract class AbstractHazelcastMessageProducer extends MessageProducerSupport { protected final DistributedObject distributedObject; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorMessageProducer.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorMessageProducer.java index 91d54191e6..b979a3d7b3 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorMessageProducer.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorMessageProducer.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,8 +50,6 @@ import org.springframework.util.Assert; * * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastClusterMonitorMessageProducer extends MessageProducerSupport { private final HazelcastInstance hazelcastInstance; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastContinuousQueryMessageProducer.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastContinuousQueryMessageProducer.java index 7a7738a7b1..9636e71564 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastContinuousQueryMessageProducer.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastContinuousQueryMessageProducer.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,8 +30,6 @@ import org.springframework.util.Assert; * @author Eren Avsarogullari * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastContinuousQueryMessageProducer extends AbstractHazelcastMessageProducer { private final String predicate; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLMessageSource.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLMessageSource.java index fc98eb4565..197a68718d 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLMessageSource.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLMessageSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,8 +36,7 @@ import org.springframework.util.CollectionUtils; * * @since 6.0 */ -@SuppressWarnings({ "rawtypes", "removal" }) -@Deprecated(forRemoval = true, since = "6.5") +@SuppressWarnings("rawtypes") public class HazelcastDistributedSQLMessageSource extends AbstractMessageSource { private final IMap distributedMap; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastEventDrivenMessageProducer.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastEventDrivenMessageProducer.java index 6f1d933c1c..788f7b16a2 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastEventDrivenMessageProducer.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/inbound/HazelcastEventDrivenMessageProducer.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,8 +49,6 @@ import org.springframework.util.Assert; * * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastEventDrivenMessageProducer extends AbstractHazelcastMessageProducer { public HazelcastEventDrivenMessageProducer(DistributedObject distributedObject) { diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/leader/LeaderInitiator.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/leader/LeaderInitiator.java index 3778fe9e3e..726aee7035 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/leader/LeaderInitiator.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/leader/LeaderInitiator.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,7 +58,6 @@ import org.springframework.util.Assert; * @author Christian Tzolov * @author Emil Palm */ -@Deprecated(forRemoval = true, since = "6.5") public class LeaderInitiator implements SmartLifecycle, DisposableBean, ApplicationEventPublisherAware { private static final LogAccessor logger = new LogAccessor(LeaderInitiator.class); diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/listener/HazelcastMembershipListener.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/listener/HazelcastMembershipListener.java index 5fa78fe265..09da083a66 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/listener/HazelcastMembershipListener.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/listener/HazelcastMembershipListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,8 +37,6 @@ import org.springframework.integration.hazelcast.HazelcastLocalInstanceRegistrar * * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastMembershipListener extends MembershipAdapter { @Override diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/lock/HazelcastLockRegistry.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/lock/HazelcastLockRegistry.java index 00f03b80b8..bc5d9da696 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/lock/HazelcastLockRegistry.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/lock/HazelcastLockRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2025 the original author or authors. + * Copyright 2017-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,6 @@ import org.springframework.util.Assert; * * @author Artem Bilan */ -@Deprecated(forRemoval = true, since = "6.5") public class HazelcastLockRegistry implements LockRegistry { private final HazelcastInstance client; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/message/EntryEventMessagePayload.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/message/EntryEventMessagePayload.java index 6a56bd5e9e..a30f9e6e47 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/message/EntryEventMessagePayload.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/message/EntryEventMessagePayload.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,6 @@ import org.springframework.util.Assert; * * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") public class EntryEventMessagePayload { /** diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/metadata/HazelcastMetadataStore.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/metadata/HazelcastMetadataStore.java index 561de7561d..b8e3f77b34 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/metadata/HazelcastMetadataStore.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/metadata/HazelcastMetadataStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2025 the original author or authors. + * Copyright 2017-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,6 @@ import org.springframework.util.Assert; * @author Vinicius Carvalho * @author Artem Bilan */ -@Deprecated(forRemoval = true, since = "6.5") public class HazelcastMetadataStore implements ListenableMetadataStore, InitializingBean { private static final String METADATA_STORE_MAP_NAME = "SPRING_INTEGRATION_METADATA_STORE"; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/outbound/HazelcastCacheWritingMessageHandler.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/outbound/HazelcastCacheWritingMessageHandler.java index 49950bea2f..89e90c3cf5 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/outbound/HazelcastCacheWritingMessageHandler.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/outbound/HazelcastCacheWritingMessageHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2015-2025 the original author or authors. + * Copyright 2015-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,8 +40,6 @@ import org.springframework.util.Assert; * * @since 6.0 */ -@Deprecated(forRemoval = true, since = "6.5") -@SuppressWarnings("removal") public class HazelcastCacheWritingMessageHandler extends AbstractMessageHandler { private DistributedObject distributedObject; diff --git a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/store/HazelcastMessageStore.java b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/store/HazelcastMessageStore.java index 26b54b18b5..b58a20927c 100644 --- a/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/store/HazelcastMessageStore.java +++ b/spring-integration-hazelcast/src/main/java/org/springframework/integration/hazelcast/store/HazelcastMessageStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2025 the original author or authors. + * Copyright 2017-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +32,6 @@ import org.springframework.util.Assert; * @author Vinicius Carvalho * @author Artem Bilan */ -@Deprecated(forRemoval = true, since = "6.5") public class HazelcastMessageStore extends AbstractKeyValueMessageStore { private static final String MESSAGE_STORE_MAP_NAME = "SPRING_INTEGRATION_MESSAGE_STORE"; diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidatorTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidatorTests-context.xml new file mode 100644 index 0000000000..4b284dfbc7 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidatorTests-context.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidatorTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidatorTests.java new file mode 100644 index 0000000000..a8bf3be7d6 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationDefinitionValidatorTests.java @@ -0,0 +1,128 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast; + +import java.util.HashSet; +import java.util.Set; + +import com.hazelcast.collection.IList; +import com.hazelcast.core.DistributedObject; +import com.hazelcast.instance.impl.HazelcastInstanceFactory; +import org.junit.AfterClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Hazelcast Integration Definition Validator Test Class + * + * @author Eren Avsarogullari + * @author Artem Bilan + * + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@DirtiesContext +@SuppressWarnings({"rawtypes"}) +public class HazelcastIntegrationDefinitionValidatorTests { + + @Autowired + private IList distList; + + @AfterClass + public static void shutdown() { + HazelcastInstanceFactory.terminateAll(); + } + + @Test + public void testValidateEnumType() { + final String cacheEventTypes = + " ADDED, REMOVED, UPDATED, EVICTED, EVICT_ALL, CLEAR_ALL "; + final Set typeSet = HazelcastIntegrationDefinitionValidator + .validateEnumType(CacheEventType.class, cacheEventTypes); + assertThat(typeSet.size()).isEqualTo(6); + for (String type : typeSet) { + Enum.valueOf(CacheEventType.class, type); + } + } + + @Test(expected = IllegalArgumentException.class) + public void testValidateEnumTypeWithInvalidValue() { + final String cacheEventTypes = "Invalid_Enum_Type"; + HazelcastIntegrationDefinitionValidator + .validateEnumType(CacheEventType.class, cacheEventTypes); + } + + @Test + public void testValidateCacheEventsByDistributedObject() { + Set cacheEventTypeSet = new HashSet<>(2); + cacheEventTypeSet.add(CacheEventType.ADDED.toString()); + cacheEventTypeSet.add(CacheEventType.REMOVED.toString()); + HazelcastIntegrationDefinitionValidator + .validateCacheEventsByDistributedObject(this.distList, cacheEventTypeSet); + } + + @Test(expected = IllegalArgumentException.class) + public void testValidateCacheEventsByDistributedObjectWithInvalidValue() { + Set cacheEventTypeSet = new HashSet<>(1); + cacheEventTypeSet.add("Invalid_Cache_Event_Type"); + HazelcastIntegrationDefinitionValidator + .validateCacheEventsByDistributedObject(this.distList, cacheEventTypeSet); + } + + @Test + public void testValidateCacheTypeForEventDrivenMessageProducer() { + HazelcastIntegrationDefinitionValidator + .validateCacheTypeForEventDrivenMessageProducer(this.distList); + } + + @Test(expected = IllegalArgumentException.class) + public void testValidateCacheTypeForEventDrivenMessageProducerWithUnexpectedDistObject() { + HazelcastIntegrationDefinitionValidator + .validateCacheTypeForEventDrivenMessageProducer(new DistributedObject() { + + @Override + public String getPartitionKey() { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public String getServiceName() { + return null; + } + + @Override + public void destroy() { + + } + + }); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationTestUser.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationTestUser.java new file mode 100644 index 0000000000..7c908f8b08 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastIntegrationTestUser.java @@ -0,0 +1,116 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast; + +import java.io.Serializable; +import java.util.Objects; + +/** + * User Bean for Hazelcast Integration Unit Tests + * + * @author Eren Avsarogullari + * @since 6.0 + */ +public class HazelcastIntegrationTestUser implements Comparable, Serializable { + + private static final long serialVersionUID = -5357485957528362705L; + + private int id; + + private String name; + + private String surname; + + private int age; + + public HazelcastIntegrationTestUser(int id, String name, String surname) { + this.id = id; + this.name = name; + this.surname = surname; + } + + public HazelcastIntegrationTestUser(int id, String name, String surname, int age) { + this.id = id; + this.name = name; + this.surname = surname; + this.age = age; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSurname() { + return surname; + } + + public void setSurname(String surname) { + this.surname = surname; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public String toString() { + return "User [id=" + id + ", name=" + name + ", surname=" + surname + ", age=" + + age + "]"; + } + + @Override + public int compareTo(HazelcastIntegrationTestUser user) { + return (this.id < user.getId()) ? -1 : (this.id > user.getId()) ? 1 : 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + HazelcastIntegrationTestUser that = (HazelcastIntegrationTestUser) o; + return id == that.id && + age == that.age && + Objects.equals(name, that.name) && + Objects.equals(surname, that.surname); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, surname, age); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastTestRequestHandlerAdvice.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastTestRequestHandlerAdvice.java new file mode 100644 index 0000000000..fc6ad49b70 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/HazelcastTestRequestHandlerAdvice.java @@ -0,0 +1,50 @@ +/* + * Copyright 2015-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast; + +import java.util.concurrent.CountDownLatch; + +import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice; +import org.springframework.messaging.Message; + +/** + * {@link AbstractRequestHandlerAdvice} advice class for Hazelcast Integration Unit Tests. + * + * @author Eren Avsarogullari + * @author Artem Bilan + * + * @since 6.0 + */ +public class HazelcastTestRequestHandlerAdvice extends AbstractRequestHandlerAdvice { + + public CountDownLatch executeLatch = null; + + public HazelcastTestRequestHandlerAdvice(int count) { + this.executeLatch = new CountDownLatch(count); + } + + @Override + protected Object doInvoke(ExecutionCallback callback, Object target, Message message) { + try { + return callback.execute(); + } + finally { + this.executeLatch.countDown(); + } + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/IdempotentReceiverIntegrationTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/IdempotentReceiverIntegrationTests.java new file mode 100644 index 0000000000..2d79873af1 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/IdempotentReceiverIntegrationTests.java @@ -0,0 +1,372 @@ +/* + * Copyright 2014-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; +import org.aopalliance.aop.Advice; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.IntegrationMessageHeaderAccessor; +import org.springframework.integration.MessageRejectedException; +import org.springframework.integration.annotation.BridgeFrom; +import org.springframework.integration.annotation.BridgeTo; +import org.springframework.integration.annotation.IdempotentReceiver; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.config.EnableIntegration; +import org.springframework.integration.config.GlobalChannelInterceptor; +import org.springframework.integration.handler.MessageProcessor; +import org.springframework.integration.handler.ServiceActivatingHandler; +import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice; +import org.springframework.integration.handler.advice.IdempotentReceiverInterceptor; +import org.springframework.integration.jmx.config.EnableIntegrationMBeanExport; +import org.springframework.integration.metadata.ConcurrentMetadataStore; +import org.springframework.integration.metadata.MetadataStore; +import org.springframework.integration.metadata.SimpleMetadataStore; +import org.springframework.integration.selector.MetadataStoreSelector; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.integration.test.util.TestUtils; +import org.springframework.integration.transaction.PseudoTransactionManager; +import org.springframework.integration.transaction.TransactionInterceptorBuilder; +import org.springframework.integration.transformer.Transformer; +import org.springframework.jmx.support.MBeanServerFactoryBean; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHandler; +import org.springframework.messaging.MessageHandlingException; +import org.springframework.messaging.PollableChannel; +import org.springframework.messaging.support.ChannelInterceptor; +import org.springframework.messaging.support.GenericMessage; +import org.springframework.stereotype.Component; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.interceptor.TransactionInterceptor; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.Mockito.spy; + +/** + * @author Artem Bilan + * @author Gary Russell + * + * @since 4.1 + */ +@SpringJUnitConfig +@DirtiesContext +public class IdempotentReceiverIntegrationTests { + + @Autowired + private MessageChannel input; + + @Autowired + private PollableChannel output; + + @Autowired + private MetadataStore store; + + @Autowired + private IdempotentReceiverInterceptor idempotentReceiverInterceptor; + + @Autowired + private AtomicInteger adviceCalled; + + @Autowired + private MessageChannel annotatedMethodChannel; + + @Autowired + private FooService fooService; + + @Autowired + private MessageChannel annotatedBeanMessageHandlerChannel; + + @Autowired + private MessageChannel annotatedBeanMessageHandlerChannel2; + + @Autowired + private MessageChannel bridgeChannel; + + @Autowired + private MessageChannel toBridgeChannel; + + @Autowired + private PollableChannel bridgePollableChannel; + + @Autowired + private AtomicBoolean txSupplied; + + @Test + @SuppressWarnings("unchecked") + public void testIdempotentReceiver() { + this.idempotentReceiverInterceptor.setThrowExceptionOnRejection(true); + TestUtils.getPropertyValue(this.store, "metadata", Map.class).clear(); + Message message = new GenericMessage<>("foo"); + this.input.send(message); + Message receive = this.output.receive(10000); + assertThat(receive).isNotNull(); + assertThat(this.adviceCalled.get()).isEqualTo(1); + assertThat(TestUtils.getPropertyValue(this.store, "metadata", Map.class)).hasSize(1); + String foo = this.store.get("foo"); + assertThat(foo).isEqualTo("FOO"); + + assertThatExceptionOfType(MessageRejectedException.class) + .isThrownBy(() -> this.input.send(message)); + + this.idempotentReceiverInterceptor.setThrowExceptionOnRejection(false); + this.input.send(message); + receive = this.output.receive(10000); + assertThat(receive).isNotNull(); + assertThat(this.adviceCalled.get()).isEqualTo(2); + assertThat(receive.getHeaders()).containsEntry(IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE, true); + assertThat(TestUtils.getPropertyValue(store, "metadata", Map.class)).hasSize(1); + + assertThat(this.txSupplied.get()).isTrue(); + } + + @Test + public void testIdempotentReceiverOnMethod() { + TestUtils.getPropertyValue(this.store, "metadata", Map.class).clear(); + Message message = new GenericMessage<>("foo"); + this.annotatedMethodChannel.send(message); + this.annotatedMethodChannel.send(message); + + assertThat(this.fooService.messages.size()).isEqualTo(2); + assertThat(this.fooService.messages.get(1) + .getHeaders()).containsEntry(IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE, true); + } + + @Test + public void testIdempotentReceiverOnBeanMessageHandler() { + PollableChannel replyChannel = new QueueChannel(); + Message message = MessageBuilder.withPayload("bar").setReplyChannel(replyChannel).build(); + this.annotatedBeanMessageHandlerChannel.send(message); + + Message receive = replyChannel.receive(10000); + assertThat(receive).isNotNull(); + assertThat(receive.getHeaders()).doesNotContainKey(IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE); + + this.annotatedBeanMessageHandlerChannel.send(message); + receive = replyChannel.receive(10000); + assertThat(receive).isNotNull(); + assertThat(receive.getHeaders()).containsEntry(IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE, true); + + this.annotatedBeanMessageHandlerChannel2.send(new GenericMessage<>("baz")); + + assertThatExceptionOfType(MessageHandlingException.class) + .isThrownBy(() -> this.annotatedBeanMessageHandlerChannel2.send(new GenericMessage<>("baz"))) + .withMessageContaining("duplicate message has been received"); + } + + @Test + public void testIdempotentReceiverOnBridgeTo() { + PollableChannel replyChannel = new QueueChannel(); + Message message = MessageBuilder.withPayload("bridgeTo").setReplyChannel(replyChannel).build(); + this.bridgeChannel.send(message); + + Message receive = replyChannel.receive(10000); + assertThat(receive).isNotNull(); + assertThat(receive.getHeaders()).doesNotContainKey(IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE); + + this.bridgeChannel.send(message); + receive = replyChannel.receive(10000); + assertThat(receive).isNotNull(); + assertThat(receive.getHeaders()).containsEntry(IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE, true); + } + + @Test + public void testIdempotentReceiverOnBridgeFrom() { + Message message = MessageBuilder.withPayload("bridgeFrom").build(); + this.toBridgeChannel.send(message); + + Message receive = this.bridgePollableChannel.receive(10000); + assertThat(receive).isNotNull(); + assertThat(receive.getHeaders()).doesNotContainKey(IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE); + + this.toBridgeChannel.send(message); + receive = this.bridgePollableChannel.receive(10000); + assertThat(receive).isNotNull(); + assertThat(receive.getHeaders()).containsEntry(IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE, true); + } + + @Configuration + @EnableIntegration + @EnableIntegrationMBeanExport(server = "mBeanServer") + public static class ContextConfiguration { + + @Bean + public static MBeanServerFactoryBean mBeanServer() { + return new MBeanServerFactoryBean(); + } + + @Bean(destroyMethod = "shutdown") + public HazelcastInstance hazelcastInstance() { + return Hazelcast.newHazelcastInstance(); + } + + @Bean + public ConcurrentMetadataStore store() { + return new SimpleMetadataStore( + hazelcastInstance() + .getMap("idempotentReceiverMetadataStore")); + } + + @Bean + public IdempotentReceiverInterceptor idempotentReceiverInterceptor() { + return new IdempotentReceiverInterceptor( + new MetadataStoreSelector( + message -> message.getPayload().toString(), + message -> message.getPayload().toString().toUpperCase(), store())); + } + + @Bean + public PlatformTransactionManager transactionManager() { + return spy(new PseudoTransactionManager()); + } + + @Bean + public TransactionInterceptor transactionInterceptor() { + return new TransactionInterceptorBuilder(true) + .build(); + } + + @Bean + public MessageChannel input() { + return new DirectChannel(); + } + + @Bean + public PollableChannel output() { + return new QueueChannel(); + } + + @Bean + public AtomicBoolean txSupplied() { + return new AtomicBoolean(); + } + + @Bean + @GlobalChannelInterceptor(patterns = "output") + public ChannelInterceptor txSuppliedChannelInterceptor(final AtomicBoolean txSupplied) { + return new ChannelInterceptor() { + + @Override + public void postSend(Message message, MessageChannel channel, boolean sent) { + txSupplied.set(TransactionSynchronizationManager.isActualTransactionActive()); + } + + }; + } + + @Bean + @org.springframework.integration.annotation.Transformer(inputChannel = "input", + outputChannel = "output", + adviceChain = {"fooAdvice", + "idempotentReceiverInterceptor", + "transactionInterceptor"}) + public Transformer transformer() { + return message -> message; + } + + @Bean + public AtomicInteger adviceCalled() { + return new AtomicInteger(); + } + + @Bean + public Advice fooAdvice(@SuppressWarnings("unused") final AtomicInteger adviceCalled) { + return new AbstractRequestHandlerAdvice() { + + @Override + protected Object doInvoke(ExecutionCallback callback, Object target, Message message) { + adviceCalled.incrementAndGet(); + return callback.execute(); + } + + }; + } + + @Bean + public MessageChannel annotatedMethodChannel() { + return new DirectChannel(); + } + + @Bean + public FooService fooService() { + return new FooService(); + } + + @Bean + @BridgeTo + @IdempotentReceiver("idempotentReceiverInterceptor") + public MessageChannel bridgeChannel() { + return new DirectChannel(); + } + + @Bean + @BridgeFrom("toBridgeChannel") + @IdempotentReceiver("idempotentReceiverInterceptor") + public PollableChannel bridgePollableChannel() { + return new QueueChannel(); + } + + @Bean + @ServiceActivator(inputChannel = "annotatedBeanMessageHandlerChannel") + @IdempotentReceiver("idempotentReceiverInterceptor") + public MessageHandler messageHandler() { + return new ServiceActivatingHandler((MessageProcessor) message -> message); + } + + @Bean + @ServiceActivator(inputChannel = "annotatedBeanMessageHandlerChannel2") + @IdempotentReceiver("idempotentReceiverInterceptor") + public MessageHandler messageHandler2() { + return message -> { + if (message.getHeaders().containsKey(IntegrationMessageHeaderAccessor.DUPLICATE_MESSAGE)) { + throw new MessageHandlingException(message, "duplicate message has been received"); + } + }; + } + + } + + @Component + private static class FooService { + + private final List> messages = new ArrayList>(); + + @ServiceActivator(inputChannel = "annotatedMethodChannel") + @IdempotentReceiver("idempotentReceiverInterceptor") + public void handle(Message message) { + this.messages.add(message); + } + + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/common-config.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/common-config.xml new file mode 100644 index 0000000000..ff7256d52e --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/common-config.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastCQDistributedMapInboundChannelAdapterTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastCQDistributedMapInboundChannelAdapterTests-context.xml new file mode 100644 index 0000000000..0ff55f49ea --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastCQDistributedMapInboundChannelAdapterTests-context.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastCQDistributedMapInboundChannelAdapterTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastCQDistributedMapInboundChannelAdapterTests.java new file mode 100644 index 0000000000..71e5cda58b --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastCQDistributedMapInboundChannelAdapterTests.java @@ -0,0 +1,157 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound; + +import com.hazelcast.core.EntryEventType; +import com.hazelcast.map.IMap; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.HazelcastHeaders; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.integration.hazelcast.message.EntryEventMessagePayload; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Hazelcast Continuous Query Inbound Channel Adapter Unit Test Class + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@DirtiesContext +@SuppressWarnings({"unchecked", "rawtypes"}) +public class HazelcastCQDistributedMapInboundChannelAdapterTests { + + @Autowired + private PollableChannel cqMapChannel1; + + @Autowired + private PollableChannel cqMapChannel2; + + @Autowired + private PollableChannel cqMapChannel3; + + @Autowired + private PollableChannel cqMapChannel4; + + @Autowired + private PollableChannel cqMapChannel5; + + @Autowired + private IMap cqDistributedMap1; + + @Autowired + private IMap cqDistributedMap2; + + @Autowired + private IMap cqDistributedMap3; + + @Autowired + private IMap cqDistributedMap4; + + @Autowired + private IMap cqDistributedMap5; + + @Test + public void testContinuousQueryForOnlyADDEDEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForADDEDDistributedMapEntryEvent(cqDistributedMap1, + cqMapChannel1, "cqDistributedMap1"); + } + + @Test + public void testContinuousQueryForOnlyREMOVEDEntryEvent() { + cqDistributedMap2 + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + cqDistributedMap2 + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2")); + cqDistributedMap2.remove(2); + Message msg = + cqMapChannel2.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(EntryEventType.REMOVED.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo("cqDistributedMap2"); + + assertThat(((EntryEventMessagePayload) msg + .getPayload()).key).isEqualTo(Integer.valueOf(2)); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getId()).isEqualTo(2); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getName()).isEqualTo("TestName2"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getSurname()).isEqualTo("TestSurname2"); + } + + @Test + public void testContinuousQueryForALLEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForDistributedMapEntryEvents(cqDistributedMap3, + cqMapChannel3, "cqDistributedMap3"); + } + + @Test + public void testContinuousQueryForOnlyUPDATEDEntryEvent() { + cqDistributedMap4 + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + cqDistributedMap4 + .put(1, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2")); + Message msg = + cqMapChannel4.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(EntryEventType.UPDATED.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo("cqDistributedMap4"); + + assertThat(((EntryEventMessagePayload) msg + .getPayload()).key).isEqualTo(Integer.valueOf(1)); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getId()).isEqualTo(1); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getName()).isEqualTo("TestName1"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getSurname()).isEqualTo("TestSurname1"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getId()).isEqualTo(2); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getName()).isEqualTo("TestName2"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getSurname()).isEqualTo("TestSurname2"); + } + + @Test + public void testContinuousQueryForOnlyUPDATEDEntryEventWhenIncludeValueIsFalse() { + HazelcastInboundChannelAdapterTestUtils + .testContinuousQueryForUPDATEDEntryEventWhenIncludeValueIsFalse( + cqDistributedMap5, cqMapChannel5, "cqDistributedMap5"); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorInboundChannelAdapterTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorInboundChannelAdapterTests-context.xml new file mode 100644 index 0000000000..8494afe00b --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorInboundChannelAdapterTests-context.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorInboundChannelAdapterTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorInboundChannelAdapterTests.java new file mode 100644 index 0000000000..5171660137 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastClusterMonitorInboundChannelAdapterTests.java @@ -0,0 +1,111 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound; + +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.core.LifecycleEvent; +import com.hazelcast.core.LifecycleEvent.LifecycleState; +import com.hazelcast.instance.impl.HazelcastInstanceFactory; +import org.junit.AfterClass; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Hazelcast Cluster Monitor Inbound Channel Adapter Unit Test Class + * + * @author Eren Avsarogullari + * @author Artem Bilan + */ +@RunWith(SpringRunner.class) +@SpringJUnitConfig +@DirtiesContext +@Ignore("Hard to reach CP consensus with limited number of members in two clusters") +public class HazelcastClusterMonitorInboundChannelAdapterTests { + + private static final String TEST_GROUP_NAME1 = "Test_Group_Name1"; + + @Autowired + private PollableChannel cmChannel1; + + @Autowired + private PollableChannel cmChannel2; + + @Autowired + private PollableChannel cmChannel3; + + @Autowired + private PollableChannel cmChannel4; + + @Autowired + private PollableChannel cmChannel5; + + @Autowired + private PollableChannel cmChannel6; + + @Autowired + private HazelcastInstance hazelcastInstance; + + @Autowired + private HazelcastInstance hazelcastInstance2; + + @Autowired + private HazelcastInstance hazelcastInstance3; + + @AfterClass + public static void shutdown() { + HazelcastInstanceFactory.terminateAll(); + } + + @Test + public void testDistributedObjectEvent() { + HazelcastInboundChannelAdapterTestUtils + .testDistributedObjectEventByChannelAndHazelcastInstance(cmChannel2, + hazelcastInstance, "Test_Distributed_Map4"); + } + + @Test + public void testLifecycleEvent() { + hazelcastInstance2.getLifecycleService().terminate(); + + Message msg = + cmChannel4.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + verifyLifecycleEvent(msg, LifecycleState.SHUTTING_DOWN); + + msg = cmChannel4.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + verifyLifecycleEvent(msg, LifecycleState.SHUTDOWN); + } + + private void verifyLifecycleEvent(final Message msg, + final LifecycleState lifecycleState) { + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof LifecycleEvent).isTrue(); + assertThat(((LifecycleEvent) msg.getPayload()).getState()).isEqualTo(lifecycleState); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedListEventDrivenInboundChannelAdapterTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedListEventDrivenInboundChannelAdapterTests-context.xml new file mode 100644 index 0000000000..23e52ac707 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedListEventDrivenInboundChannelAdapterTests-context.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedListEventDrivenInboundChannelAdapterTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedListEventDrivenInboundChannelAdapterTests.java new file mode 100644 index 0000000000..39aff6b3f4 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedListEventDrivenInboundChannelAdapterTests.java @@ -0,0 +1,100 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound; + +import com.hazelcast.collection.IList; +import com.hazelcast.core.EntryEventType; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.HazelcastHeaders; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Hazelcast Distributed List Event Driven Inbound Channel Adapter Test Class + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@DirtiesContext +@SuppressWarnings({"unchecked", "rawtypes"}) +public class HazelcastDistributedListEventDrivenInboundChannelAdapterTests { + + @Autowired + private PollableChannel edListChannel1; + + @Autowired + private PollableChannel edListChannel2; + + @Autowired + private PollableChannel edListChannel3; + + @Autowired + private IList edDistributedList1; + + @Autowired + private IList edDistributedList2; + + @Autowired + private IList edDistributedList3; + + @Test + public void testEventDrivenForOnlyADDEDEntryEvent() { + edDistributedList1.add(new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + Message msg = edListChannel1.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE).toString()).isEqualTo(EntryEventType.ADDED.toString()); + assertThat(((HazelcastIntegrationTestUser) msg.getPayload()).getId()).isEqualTo(1); + assertThat(((HazelcastIntegrationTestUser) msg.getPayload()).getName()).isEqualTo("TestName1"); + assertThat(((HazelcastIntegrationTestUser) msg.getPayload()).getSurname()).isEqualTo("TestSurname1"); + } + + @Test + public void testEventDrivenForOnlyREMOVEDEntryEvent() { + HazelcastIntegrationTestUser user = new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2"); + edDistributedList2.add(user); + edDistributedList2.remove(user); + Message msg = edListChannel2.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE).toString()).isEqualTo(EntryEventType.REMOVED.toString()); + assertThat(((HazelcastIntegrationTestUser) msg.getPayload()).getId()).isEqualTo(2); + assertThat(((HazelcastIntegrationTestUser) msg.getPayload()).getName()).isEqualTo("TestName2"); + assertThat(((HazelcastIntegrationTestUser) msg.getPayload()).getSurname()).isEqualTo("TestSurname2"); + } + + @Test + public void testEventDrivenForALLEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForDistributedCollectionItemEvents(edDistributedList3, edListChannel3); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedMapEventDrivenInboundChannelAdapterTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedMapEventDrivenInboundChannelAdapterTests-context.xml new file mode 100644 index 0000000000..1664db3047 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedMapEventDrivenInboundChannelAdapterTests-context.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedMapEventDrivenInboundChannelAdapterTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedMapEventDrivenInboundChannelAdapterTests.java new file mode 100644 index 0000000000..613521adb0 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedMapEventDrivenInboundChannelAdapterTests.java @@ -0,0 +1,144 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound; + +import com.hazelcast.core.EntryEventType; +import com.hazelcast.map.IMap; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.HazelcastHeaders; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.integration.hazelcast.message.EntryEventMessagePayload; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Hazelcast Distributed Map Event Driven Inbound Channel Adapter Test + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@DirtiesContext +@SuppressWarnings({"unchecked", "rawtypes"}) +public class HazelcastDistributedMapEventDrivenInboundChannelAdapterTests { + + @Autowired + private PollableChannel edMapChannel1; + + @Autowired + private PollableChannel edMapChannel2; + + @Autowired + private PollableChannel edMapChannel3; + + @Autowired + private PollableChannel edMapChannel4; + + @Autowired + private IMap edDistributedMap1; + + @Autowired + private IMap edDistributedMap2; + + @Autowired + private IMap edDistributedMap3; + + @Autowired + private IMap edDistributedMap4; + + @Test + public void testEventDrivenForOnlyADDEDEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForADDEDDistributedMapEntryEvent(edDistributedMap1, + edMapChannel1, "edDistributedMap1"); + } + + @Test + public void testEventDrivenForOnlyUPDATEDEntryEvent() { + edDistributedMap2 + .put(2, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + edDistributedMap2 + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2")); + Message msg = + edMapChannel2.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(EntryEventType.UPDATED.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo("edDistributedMap2"); + + assertThat(((EntryEventMessagePayload) msg + .getPayload()).key).isEqualTo(Integer.valueOf(2)); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getId()).isEqualTo(1); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getName()).isEqualTo("TestName1"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getSurname()).isEqualTo("TestSurname1"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getId()).isEqualTo(2); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getName()).isEqualTo("TestName2"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getSurname()).isEqualTo("TestSurname2"); + } + + @Test + public void testEventDrivenForOnlyREMOVEDEntryEvent() { + edDistributedMap3 + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + edDistributedMap3 + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2")); + edDistributedMap3.remove(2); + Message msg = + edMapChannel3.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(EntryEventType.REMOVED.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo("edDistributedMap3"); + + assertThat(((EntryEventMessagePayload) msg + .getPayload()).key).isEqualTo(Integer.valueOf(2)); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getId()).isEqualTo(2); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getName()).isEqualTo("TestName2"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getSurname()).isEqualTo("TestSurname2"); + } + + @Test + public void testEventDrivenForALLEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForDistributedMapEntryEvents(edDistributedMap4, edMapChannel4, + "edDistributedMap4"); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedQueueEventDrivenInboundChannelAdapterTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedQueueEventDrivenInboundChannelAdapterTests-context.xml new file mode 100644 index 0000000000..315f221482 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedQueueEventDrivenInboundChannelAdapterTests-context.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedQueueEventDrivenInboundChannelAdapterTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedQueueEventDrivenInboundChannelAdapterTests.java new file mode 100644 index 0000000000..55376190ec --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedQueueEventDrivenInboundChannelAdapterTests.java @@ -0,0 +1,105 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound; + +import com.hazelcast.collection.IQueue; +import com.hazelcast.core.EntryEventType; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.HazelcastHeaders; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Hazelcast Distributed Queue Event Driven Inbound Channel Adapter Test + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@DirtiesContext +@SuppressWarnings({"unchecked", "rawtypes"}) +public class HazelcastDistributedQueueEventDrivenInboundChannelAdapterTests { + + @Autowired + private PollableChannel edQueueChannel1; + + @Autowired + private PollableChannel edQueueChannel2; + + @Autowired + private PollableChannel edQueueChannel3; + + @Autowired + private IQueue edDistributedQueue1; + + @Autowired + private IQueue edDistributedQueue2; + + @Autowired + private IQueue edDistributedQueue3; + + @Test + public void testEventDrivenForOnlyADDEDEntryEvent() { + edDistributedQueue1 + .add(new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + Message msg = + edQueueChannel1.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE).toString()).isEqualTo(EntryEventType.ADDED.toString()); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getId())).isEqualTo(1); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getName())).isEqualTo("TestName1"); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getSurname())).isEqualTo("TestSurname1"); + } + + @Test + public void testEventDrivenForOnlyREMOVEDEntryEvent() { + HazelcastIntegrationTestUser user = + new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2"); + edDistributedQueue2.add(user); + edDistributedQueue2.remove(user); + Message msg = + edQueueChannel2.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE).toString()).isEqualTo(EntryEventType.REMOVED.toString()); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getId())).isEqualTo(2); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getName())).isEqualTo("TestName2"); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getSurname())).isEqualTo("TestSurname2"); + } + + @Test + public void testEventDrivenForALLEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForDistributedCollectionItemEvents(edDistributedQueue3, + edQueueChannel3); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLInboundChannelAdapterTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLInboundChannelAdapterTests-context.xml new file mode 100644 index 0000000000..9eeef6df64 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLInboundChannelAdapterTests-context.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLInboundChannelAdapterTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLInboundChannelAdapterTests.java new file mode 100644 index 0000000000..5deb3f0458 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSQLInboundChannelAdapterTests.java @@ -0,0 +1,90 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound; + +import com.hazelcast.map.IMap; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Hazelcast Distributed SQL Inbound Channel Adapter Test + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@DirtiesContext +@SuppressWarnings({"unchecked", "rawtypes"}) +public class HazelcastDistributedSQLInboundChannelAdapterTests { + + @Autowired + private PollableChannel dsMapChannel1; + + @Autowired + private PollableChannel dsMapChannel2; + + @Autowired + private PollableChannel dsMapChannel3; + + @Autowired + private PollableChannel dsMapChannel4; + + @Autowired + private IMap dsDistributedMap1; + + @Autowired + private IMap dsDistributedMap2; + + @Autowired + private IMap dsDistributedMap3; + + @Autowired + private IMap dsDistributedMap4; + + @Test + public void testDistributedSQLForOnlyENTRYIterationType() { + HazelcastInboundChannelAdapterTestUtils + .testDistributedSQLForENTRYIterationType(dsDistributedMap1, dsMapChannel1); + } + + @Test + public void testDistributedSQLForOnlyKEYIterationType() { + HazelcastInboundChannelAdapterTestUtils + .testDistributedSQLForKEYIterationType(dsDistributedMap2, dsMapChannel2); + } + + @Test + public void testDistributedSQLForOnlyLOCAL_KEYIterationType() { + HazelcastInboundChannelAdapterTestUtils + .testDistributedSQLForLOCAL_KEYIterationType(dsDistributedMap3, dsMapChannel3); + } + + @Test + public void testDistributedSQLForOnlyVALUEIterationType() { + HazelcastInboundChannelAdapterTestUtils + .testDistributedSQLForVALUEIterationType(dsDistributedMap4, dsMapChannel4); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSetEventDrivenInboundChannelAdapterTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSetEventDrivenInboundChannelAdapterTests-context.xml new file mode 100644 index 0000000000..416b1f29a5 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSetEventDrivenInboundChannelAdapterTests-context.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSetEventDrivenInboundChannelAdapterTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSetEventDrivenInboundChannelAdapterTests.java new file mode 100644 index 0000000000..0b66aa002e --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedSetEventDrivenInboundChannelAdapterTests.java @@ -0,0 +1,105 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound; + +import com.hazelcast.collection.ISet; +import com.hazelcast.core.EntryEventType; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.HazelcastHeaders; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Hazelcast Distributed Set Event Driven Inbound Channel Adapter Test + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@DirtiesContext +@SuppressWarnings({"unchecked", "rawtypes"}) +public class HazelcastDistributedSetEventDrivenInboundChannelAdapterTests { + + @Autowired + private PollableChannel edSetChannel1; + + @Autowired + private PollableChannel edSetChannel2; + + @Autowired + private PollableChannel edSetChannel3; + + @Autowired + private ISet edDistributedSet1; + + @Autowired + private ISet edDistributedSet2; + + @Autowired + private ISet edDistributedSet3; + + @Test + public void testEventDrivenForOnlyADDEDEntryEvent() { + edDistributedSet1 + .add(new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + Message msg = + edSetChannel1.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE).toString()).isEqualTo(EntryEventType.ADDED.toString()); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getId())).isEqualTo(1); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getName())).isEqualTo("TestName1"); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getSurname())).isEqualTo("TestSurname1"); + } + + @Test + public void testEventDrivenForOnlyREMOVEDEntryEvent() { + HazelcastIntegrationTestUser user = + new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2"); + edDistributedSet2.add(user); + edDistributedSet2.remove(user); + Message msg = + edSetChannel2.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE).toString()).isEqualTo(EntryEventType.REMOVED.toString()); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getId())).isEqualTo(2); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getName())).isEqualTo("TestName2"); + assertThat((((HazelcastIntegrationTestUser) msg.getPayload()).getSurname())).isEqualTo("TestSurname2"); + } + + @Test + public void testEventDrivenForALLEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForDistributedCollectionItemEvents(edDistributedSet3, + edSetChannel3); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedTopicEventDrivenInboundChannelAdapterTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedTopicEventDrivenInboundChannelAdapterTests-context.xml new file mode 100644 index 0000000000..655d4fce5d --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedTopicEventDrivenInboundChannelAdapterTests-context.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedTopicEventDrivenInboundChannelAdapterTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedTopicEventDrivenInboundChannelAdapterTests.java new file mode 100644 index 0000000000..a2440edbac --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastDistributedTopicEventDrivenInboundChannelAdapterTests.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound; + +import com.hazelcast.topic.ITopic; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Hazelcast Distributed Topic Event Driven Inbound Channel Adapter Test + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@DirtiesContext +@SuppressWarnings({"unchecked", "rawtypes"}) +public class HazelcastDistributedTopicEventDrivenInboundChannelAdapterTests { + + @Autowired + private PollableChannel edTopicChannel1; + + @Autowired + private ITopic edDistributedTopic1; + + @Test + public void testEventDrivenForOnlyADDEDEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForTopicMessageEvent(edDistributedTopic1, edTopicChannel1); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastMultiMapEventDrivenInboundChannelAdapterTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastMultiMapEventDrivenInboundChannelAdapterTests-context.xml new file mode 100644 index 0000000000..90fbb6b13a --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastMultiMapEventDrivenInboundChannelAdapterTests-context.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastMultiMapEventDrivenInboundChannelAdapterTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastMultiMapEventDrivenInboundChannelAdapterTests.java new file mode 100644 index 0000000000..07e4e8e8a6 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastMultiMapEventDrivenInboundChannelAdapterTests.java @@ -0,0 +1,125 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound; + +import com.hazelcast.core.EntryEventType; +import com.hazelcast.multimap.MultiMap; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.HazelcastHeaders; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.integration.hazelcast.message.EntryEventMessagePayload; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Hazelcast MultiMap Event Driven Inbound Channel Adapter Test + * + * @author Eren Avsarogullari + * @author Artem Bilan + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@DirtiesContext +@SuppressWarnings({"unchecked", "rawtypes"}) +public class HazelcastMultiMapEventDrivenInboundChannelAdapterTests { + + @Autowired + private PollableChannel edMultiMapChannel1; + + @Autowired + private PollableChannel edMultiMapChannel2; + + @Autowired + private PollableChannel edMultiMapChannel3; + + @Autowired + private MultiMap edMultiMap1; + + @Autowired + private MultiMap edMultiMap2; + + @Autowired + private MultiMap edMultiMap3; + + @Test + public void testEventDrivenForOnlyADDEDEntryEvent() { + edMultiMap1 + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + Message msg = + edMultiMapChannel1.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(EntryEventType.ADDED.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo("edMultiMap1"); + + assertThat(((EntryEventMessagePayload) msg + .getPayload()).key).isEqualTo(Integer.valueOf(1)); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getId()).isEqualTo(1); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getName()).isEqualTo("TestName1"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getSurname()).isEqualTo("TestSurname1"); + } + + @Test + public void testEventDrivenForOnlyREMOVEDEntryEvent() { + edMultiMap2 + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + edMultiMap2 + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2")); + edMultiMap2.remove(2); + Message msg = + edMultiMapChannel2.receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(EntryEventType.REMOVED.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo("edMultiMap2"); + + assertThat(((EntryEventMessagePayload) msg + .getPayload()).key).isEqualTo(Integer.valueOf(2)); + assertThat(((EntryEventMessagePayload) msg.getPayload()).value).isNull(); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getId()).isEqualTo(2); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getName()).isEqualTo("TestName2"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getSurname()).isEqualTo("TestSurname2"); + } + + @Test + public void testEventDrivenForALLEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForMultiMapEntryEvents(edMultiMap3, edMultiMapChannel3, + "edMultiMap3"); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastReplicatedMapEventDrivenInboundChannelAdapterTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastReplicatedMapEventDrivenInboundChannelAdapterTests-context.xml new file mode 100644 index 0000000000..4e7163f717 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastReplicatedMapEventDrivenInboundChannelAdapterTests-context.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastReplicatedMapEventDrivenInboundChannelAdapterTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastReplicatedMapEventDrivenInboundChannelAdapterTests.java new file mode 100644 index 0000000000..306c80ae6c --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/HazelcastReplicatedMapEventDrivenInboundChannelAdapterTests.java @@ -0,0 +1,161 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound; + +import com.hazelcast.core.EntryEventType; +import com.hazelcast.replicatedmap.ReplicatedMap; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.HazelcastHeaders; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.integration.hazelcast.message.EntryEventMessagePayload; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Hazelcast Replicated Map Event Driven Inbound Channel Adapter Test + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@DirtiesContext +@SuppressWarnings({"unchecked", "rawtypes"}) +public class HazelcastReplicatedMapEventDrivenInboundChannelAdapterTests { + + @Autowired + private PollableChannel edReplicatedMapChannel1; + + @Autowired + private PollableChannel edReplicatedMapChannel2; + + @Autowired + private PollableChannel edReplicatedMapChannel3; + + @Autowired + private PollableChannel edReplicatedMapChannel4; + + @Autowired + private ReplicatedMap edReplicatedMap1; + + @Autowired + private ReplicatedMap edReplicatedMap2; + + @Autowired + private ReplicatedMap edReplicatedMap3; + + @Autowired + private ReplicatedMap edReplicatedMap4; + + @Test + public void testEventDrivenForOnlyADDEDEntryEvent() { + edReplicatedMap1 + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + Message msg = edReplicatedMapChannel1 + .receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(EntryEventType.ADDED.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo("edReplicatedMap1"); + + assertThat(((EntryEventMessagePayload) msg + .getPayload()).key).isEqualTo(Integer.valueOf(1)); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getId()).isEqualTo(1); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getName()).isEqualTo("TestName1"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getSurname()).isEqualTo("TestSurname1"); + } + + @Test + public void testEventDrivenForOnlyUPDATEDEntryEvent() { + edReplicatedMap2 + .put(2, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + edReplicatedMap2 + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2")); + Message msg = edReplicatedMapChannel2 + .receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(EntryEventType.UPDATED.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo("edReplicatedMap2"); + + assertThat(((EntryEventMessagePayload) msg + .getPayload()).key).isEqualTo(Integer.valueOf(2)); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getId()).isEqualTo(1); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getName()).isEqualTo("TestName1"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getSurname()).isEqualTo("TestSurname1"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getId()).isEqualTo(2); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getName()).isEqualTo("TestName2"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getSurname()).isEqualTo("TestSurname2"); + } + + @Test + public void testEventDrivenForOnlyREMOVEDEntryEvent() { + edReplicatedMap3 + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + edReplicatedMap3 + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2")); + edReplicatedMap3.remove(2); + Message msg = edReplicatedMapChannel3 + .receive(HazelcastInboundChannelAdapterTestUtils.TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(EntryEventType.REMOVED.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo("edReplicatedMap3"); + + assertThat(((EntryEventMessagePayload) msg + .getPayload()).key).isEqualTo(Integer.valueOf(2)); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getId()).isEqualTo(2); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getName()).isEqualTo("TestName2"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).oldValue).getSurname()).isEqualTo("TestSurname2"); + } + + @Test + public void testEventDrivenForALLEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForReplicatedMapEntryEvents(edReplicatedMap4, + edReplicatedMapChannel4, "edReplicatedMap4"); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastCQDistributedMapInboundChannelAdapterConfigTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastCQDistributedMapInboundChannelAdapterConfigTests.java new file mode 100644 index 0000000000..8d3dc72402 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastCQDistributedMapInboundChannelAdapterConfigTests.java @@ -0,0 +1,84 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound.config; + +import com.hazelcast.map.IMap; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +/** + * Hazelcast Continuous Query Inbound Channel Adapter JavaConfig driven Unit Test Class + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = HazelcastIntegrationInboundTestConfiguration.class, + loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class HazelcastCQDistributedMapInboundChannelAdapterConfigTests { + + @Autowired + private PollableChannel cqDistributedMapChannel1; + + @Autowired + private PollableChannel cqDistributedMapChannel2; + + @Autowired + private PollableChannel cqDistributedMapChannel3; + + @Autowired + private IMap testCQDistributedMap1; + + @Autowired + private IMap testCQDistributedMap2; + + @Autowired + private IMap testCQDistributedMap3; + + @Test + public void testContinuousQueryForADDEDEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForADDEDDistributedMapEntryEvent(testCQDistributedMap1, + cqDistributedMapChannel1, "Test_CQ_Distributed_Map1"); + } + + @Test + public void testContinuousQueryForALLEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForDistributedMapEntryEvents(testCQDistributedMap2, + cqDistributedMapChannel2, "Test_CQ_Distributed_Map2"); + } + + @Test + public void testContinuousQueryForUPDATEDEntryEventWhenIncludeValueIsFalse() { + HazelcastInboundChannelAdapterTestUtils + .testContinuousQueryForUPDATEDEntryEventWhenIncludeValueIsFalse( + testCQDistributedMap3, cqDistributedMapChannel3, + "Test_CQ_Distributed_Map3"); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastClusterMonitorInboundChannelAdapterConfigTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastClusterMonitorInboundChannelAdapterConfigTests.java new file mode 100644 index 0000000000..6b550c03ce --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastClusterMonitorInboundChannelAdapterConfigTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound.config; + +import com.hazelcast.core.HazelcastInstance; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Hazelcast Cluster Monitor Inbound Channel Adapter JavaConfig driven Unit Test Class + * + * @author Eren Avsarogullari + * @since 6.0 + */ + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = HazelcastIntegrationInboundTestConfiguration.class) +@DirtiesContext +public class HazelcastClusterMonitorInboundChannelAdapterConfigTests { + + @Autowired + private PollableChannel cmonChannel; + + @Autowired + private PollableChannel cmonChannel2; + + @Autowired + private HazelcastInstance testHazelcastInstance; + + @Test + public void testConfigDrivenDistributedObjectEvent() { + HazelcastInboundChannelAdapterTestUtils + .testDistributedObjectEventByChannelAndHazelcastInstance(cmonChannel2, + testHazelcastInstance, "Test_Distributed_Map3"); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastDistributedSQLInboundChannelAdapterConfigTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastDistributedSQLInboundChannelAdapterConfigTests.java new file mode 100644 index 0000000000..e5d8921ca5 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastDistributedSQLInboundChannelAdapterConfigTests.java @@ -0,0 +1,96 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound.config; + +import com.hazelcast.map.IMap; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +/** + * Hazelcast Distributed SQL Inbound Channel Adapter JavaConfig driven Unit Test Class + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = HazelcastIntegrationInboundTestConfiguration.class, + loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class HazelcastDistributedSQLInboundChannelAdapterConfigTests { + + @Autowired + private PollableChannel dsDistributedMapChannel; + + @Autowired + private PollableChannel dsDistributedMapChannel2; + + @Autowired + private PollableChannel dsDistributedMapChannel3; + + @Autowired + private PollableChannel dsDistributedMapChannel4; + + @Autowired + private IMap testDSDistributedMap; + + @Autowired + private IMap testDSDistributedMap2; + + @Autowired + private IMap testDSDistributedMap3; + + @Autowired + private IMap testDSDistributedMap4; + + @Test + public void testDistributedSQLForENTRYIterationType() { + HazelcastInboundChannelAdapterTestUtils + .testDistributedSQLForENTRYIterationType(testDSDistributedMap, + dsDistributedMapChannel); + } + + @Test + public void testDistributedSQLForKEYIterationType() { + HazelcastInboundChannelAdapterTestUtils + .testDistributedSQLForKEYIterationType(testDSDistributedMap2, + dsDistributedMapChannel2); + } + + @Test + public void testDistributedSQLForLOCAL_KEYIterationType() { + HazelcastInboundChannelAdapterTestUtils + .testDistributedSQLForLOCAL_KEYIterationType(testDSDistributedMap3, + dsDistributedMapChannel3); + } + + @Test + public void testDistributedSQLForVALUEIterationType() { + HazelcastInboundChannelAdapterTestUtils + .testDistributedSQLForVALUEIterationType(testDSDistributedMap4, + dsDistributedMapChannel4); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastEventDrivenInboundChannelAdapterConfigTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastEventDrivenInboundChannelAdapterConfigTests.java new file mode 100644 index 0000000000..31dde31112 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastEventDrivenInboundChannelAdapterConfigTests.java @@ -0,0 +1,153 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound.config; + +import com.hazelcast.collection.IList; +import com.hazelcast.collection.IQueue; +import com.hazelcast.collection.ISet; +import com.hazelcast.map.IMap; +import com.hazelcast.multimap.MultiMap; +import com.hazelcast.replicatedmap.ReplicatedMap; +import com.hazelcast.topic.ITopic; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.inbound.util.HazelcastInboundChannelAdapterTestUtils; +import org.springframework.messaging.PollableChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +/** + * Hazelcast Event Driven Inbound Channel Adapter JavaConfig driven Unit Test Class + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = HazelcastIntegrationInboundTestConfiguration.class, + loader = AnnotationConfigContextLoader.class) +@DirtiesContext +public class HazelcastEventDrivenInboundChannelAdapterConfigTests { + + @Autowired + private PollableChannel distributedMapChannel; + + @Autowired + private PollableChannel distributedMapChannel2; + + @Autowired + private PollableChannel distributedListChannel; + + @Autowired + private PollableChannel distributedSetChannel; + + @Autowired + private PollableChannel distributedQueueChannel; + + @Autowired + private PollableChannel topicChannel; + + @Autowired + private PollableChannel replicatedMapChannel; + + @Autowired + private PollableChannel multiMapChannel; + + @Autowired + private IMap testDistributedMap; + + @Autowired + private IMap testDistributedMap2; + + @Autowired + private IList testDistributedList; + + @Autowired + private ISet testDistributedSet; + + @Autowired + private IQueue testDistributedQueue; + + @Autowired + private ITopic testTopic; + + @Autowired + private ReplicatedMap testReplicatedMap; + + @Autowired + private MultiMap testMultiMap; + + @Test + public void testEventDrivenForADDEDEntryEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForADDEDDistributedMapEntryEvent(testDistributedMap, + distributedMapChannel, "Test_Distributed_Map"); + } + + @Test + public void testEventDrivenForEntryEvents() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForDistributedMapEntryEvents(testDistributedMap2, + distributedMapChannel2, "Test_Distributed_Map2"); + } + + @Test + public void testEventDrivenForDistributedListItemEvents() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForDistributedCollectionItemEvents(testDistributedList, + distributedListChannel); + } + + @Test + public void testEventDrivenForDistributedSetItemEvents() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForDistributedCollectionItemEvents(testDistributedSet, + distributedSetChannel); + } + + @Test + public void testEventDrivenForDistributedQueueItemEvents() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForDistributedCollectionItemEvents(testDistributedQueue, + distributedQueueChannel); + } + + @Test + public void testEventDrivenForADDEDMessageEvent() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForTopicMessageEvent(testTopic, topicChannel); + } + + @Test + public void testEventDrivenForReplicatedMapEntryEvents() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForReplicatedMapEntryEvents(testReplicatedMap, + replicatedMapChannel, "Test_Replicated_Map"); + } + + @Test + public void testEventDrivenForMultiMapEntryEvents() { + HazelcastInboundChannelAdapterTestUtils + .testEventDrivenForMultiMapEntryEvents(testMultiMap, multiMapChannel, + "Test_Multi_Map"); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastIntegrationInboundTestConfiguration.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastIntegrationInboundTestConfiguration.java new file mode 100644 index 0000000000..15e8f5d10d --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/config/HazelcastIntegrationInboundTestConfiguration.java @@ -0,0 +1,394 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound.config; + +import com.hazelcast.collection.IList; +import com.hazelcast.collection.IQueue; +import com.hazelcast.collection.ISet; +import com.hazelcast.config.Config; +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.map.IMap; +import com.hazelcast.multimap.MultiMap; +import com.hazelcast.replicatedmap.ReplicatedMap; +import com.hazelcast.topic.ITopic; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.annotation.InboundChannelAdapter; +import org.springframework.integration.annotation.Poller; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.config.EnableIntegration; +import org.springframework.integration.hazelcast.DistributedSQLIterationType; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.HazelcastLocalInstanceRegistrar; +import org.springframework.integration.hazelcast.inbound.HazelcastClusterMonitorMessageProducer; +import org.springframework.integration.hazelcast.inbound.HazelcastContinuousQueryMessageProducer; +import org.springframework.integration.hazelcast.inbound.HazelcastDistributedSQLMessageSource; +import org.springframework.integration.hazelcast.inbound.HazelcastEventDrivenMessageProducer; +import org.springframework.messaging.PollableChannel; + +/** + * Configuration Class for Hazelcast Integration Inbound Test + * + * @author Eren Avsarogullari + * @author Artem Bilan + */ +@Configuration +@EnableIntegration +public class HazelcastIntegrationInboundTestConfiguration { + + @Bean + public PollableChannel distributedMapChannel() { + return new QueueChannel(); + } + + @Bean + public PollableChannel distributedMapChannel2() { + return new QueueChannel(); + } + + @Bean + public PollableChannel distributedListChannel() { + return new QueueChannel(); + } + + @Bean + public PollableChannel distributedSetChannel() { + return new QueueChannel(); + } + + @Bean + public PollableChannel distributedQueueChannel() { + return new QueueChannel(); + } + + @Bean + public PollableChannel topicChannel() { + return new QueueChannel(); + } + + @Bean + public PollableChannel multiMapChannel() { + return new QueueChannel(); + } + + @Bean + public PollableChannel replicatedMapChannel() { + return new QueueChannel(); + } + + @Bean + public PollableChannel cqDistributedMapChannel1() { + return new QueueChannel(); + } + + @Bean + public PollableChannel cqDistributedMapChannel2() { + return new QueueChannel(); + } + + @Bean + public PollableChannel cqDistributedMapChannel3() { + return new QueueChannel(); + } + + @Bean + public PollableChannel dsDistributedMapChannel() { + return new QueueChannel(); + } + + @Bean + public PollableChannel dsDistributedMapChannel2() { + return new QueueChannel(); + } + + @Bean + public PollableChannel dsDistributedMapChannel3() { + return new QueueChannel(); + } + + @Bean + public PollableChannel dsDistributedMapChannel4() { + return new QueueChannel(); + } + + @Bean + public PollableChannel cmonChannel() { + return new QueueChannel(); + } + + @Bean + public PollableChannel cmonChannel2() { + return new QueueChannel(); + } + + @Bean + public IMap testDistributedMap() { + return testHazelcastInstance().getMap("Test_Distributed_Map"); + } + + @Bean + public IMap testDistributedMap2() { + return testHazelcastInstance().getMap("Test_Distributed_Map2"); + } + + @Bean + public IList testDistributedList() { + return testHazelcastInstance().getList("Test_Distributed_List"); + } + + @Bean + public ISet testDistributedSet() { + return testHazelcastInstance().getSet("Test_Distributed_Set"); + } + + @Bean + public IQueue testDistributedQueue() { + return testHazelcastInstance().getQueue("Test_Distributed_Queue"); + } + + @Bean + public ITopic testTopic() { + return testHazelcastInstance().getTopic("Test_Topic"); + } + + @Bean + public MultiMap testMultiMap() { + return testHazelcastInstance().getMultiMap("Test_Multi_Map"); + } + + @Bean + public ReplicatedMap testReplicatedMap() { + return testHazelcastInstance().getReplicatedMap("Test_Replicated_Map"); + } + + @Bean + public IMap testCQDistributedMap1() { + return testHazelcastInstance().getMap("Test_CQ_Distributed_Map1"); + } + + @Bean + public IMap testCQDistributedMap2() { + return testHazelcastInstance().getMap("Test_CQ_Distributed_Map2"); + } + + @Bean + public IMap testCQDistributedMap3() { + return testHazelcastInstance().getMap("Test_CQ_Distributed_Map3"); + } + + @Bean + public IMap testDSDistributedMap() { + return testHazelcastInstance().getMap("Test_DS_Distributed_Map"); + } + + @Bean + public IMap testDSDistributedMap2() { + return testHazelcastInstance().getMap("Test_DS_Distributed_Map2"); + } + + @Bean + public IMap testDSDistributedMap3() { + return testHazelcastInstance().getMap("Test_DS_Distributed_Map3"); + } + + @Bean + public IMap testDSDistributedMap4() { + return testHazelcastInstance().getMap("Test_DS_Distributed_Map4"); + } + + @Bean + public Config hazelcastConfig() { + Config config = new Config(); + config.getCPSubsystemConfig().setCPMemberCount(0) + .setSessionHeartbeatIntervalSeconds(1); + return config; + } + + @Bean(destroyMethod = "shutdown") + public HazelcastInstance testHazelcastInstance() { + return Hazelcast.newHazelcastInstance(hazelcastConfig()); + } + + @Bean(HazelcastLocalInstanceRegistrar.BEAN_NAME) + public HazelcastLocalInstanceRegistrar hazelcastLocalInstanceRegistrar() { + return new HazelcastLocalInstanceRegistrar(testHazelcastInstance()); + } + + @Bean + public HazelcastEventDrivenMessageProducer hazelcastEventDrivenMessageProducer() { + final HazelcastEventDrivenMessageProducer producer = + new HazelcastEventDrivenMessageProducer(testDistributedMap()); + producer.setOutputChannel(distributedMapChannel()); + return producer; + } + + @Bean + public HazelcastEventDrivenMessageProducer hazelcastEventDrivenMessageProducer2() { + final HazelcastEventDrivenMessageProducer producer = + new HazelcastEventDrivenMessageProducer(testDistributedMap2()); + producer.setOutputChannel(distributedMapChannel2()); + producer.setCacheEventTypes("ADDED,REMOVED,UPDATED,CLEAR_ALL"); + return producer; + } + + @Bean + public HazelcastEventDrivenMessageProducer hazelcastEventDrivenMessageProducer3() { + final HazelcastEventDrivenMessageProducer producer = + new HazelcastEventDrivenMessageProducer(testDistributedList()); + producer.setOutputChannel(distributedListChannel()); + producer.setCacheEventTypes("ADDED,REMOVED"); + return producer; + } + + @Bean + public HazelcastEventDrivenMessageProducer hazelcastEventDrivenMessageProducer4() { + final HazelcastEventDrivenMessageProducer producer = + new HazelcastEventDrivenMessageProducer(testDistributedSet()); + producer.setOutputChannel(distributedSetChannel()); + producer.setCacheEventTypes("ADDED,REMOVED"); + return producer; + } + + @Bean + public HazelcastEventDrivenMessageProducer hazelcastEventDrivenMessageProducer5() { + final HazelcastEventDrivenMessageProducer producer = + new HazelcastEventDrivenMessageProducer(testDistributedQueue()); + producer.setOutputChannel(distributedQueueChannel()); + producer.setCacheEventTypes("ADDED,REMOVED"); + return producer; + } + + @Bean + public HazelcastEventDrivenMessageProducer hazelcastEventDrivenMessageProducer6() { + final HazelcastEventDrivenMessageProducer producer = + new HazelcastEventDrivenMessageProducer(testTopic()); + producer.setOutputChannel(topicChannel()); + return producer; + } + + @Bean + public HazelcastEventDrivenMessageProducer hazelcastEventDrivenMessageProducer7() { + final HazelcastEventDrivenMessageProducer producer = + new HazelcastEventDrivenMessageProducer(testReplicatedMap()); + producer.setOutputChannel(replicatedMapChannel()); + producer.setCacheEventTypes("ADDED,REMOVED,UPDATED"); + return producer; + } + + @Bean + public HazelcastEventDrivenMessageProducer hazelcastEventDrivenMessageProducer8() { + final HazelcastEventDrivenMessageProducer producer = + new HazelcastEventDrivenMessageProducer(testMultiMap()); + producer.setOutputChannel(multiMapChannel()); + producer.setCacheEventTypes("ADDED,REMOVED,CLEAR_ALL"); + return producer; + } + + @Bean + public HazelcastContinuousQueryMessageProducer hazelcastContinuousQueryMessageProducer() { + final HazelcastContinuousQueryMessageProducer producer = + new HazelcastContinuousQueryMessageProducer(testCQDistributedMap1(), + "name=TestName1"); + producer.setOutputChannel(cqDistributedMapChannel1()); + return producer; + } + + @Bean + public HazelcastContinuousQueryMessageProducer hazelcastContinuousQueryMessageProducer2() { + final HazelcastContinuousQueryMessageProducer producer = + new HazelcastContinuousQueryMessageProducer(testCQDistributedMap2(), + "name=TestName1 OR name=TestName2"); + producer.setOutputChannel(cqDistributedMapChannel2()); + producer.setCacheEventTypes("ADDED,REMOVED,UPDATED,CLEAR_ALL"); + return producer; + } + + @Bean + public HazelcastContinuousQueryMessageProducer hazelcastContinuousQueryMessageProducer3() { + final HazelcastContinuousQueryMessageProducer producer = + new HazelcastContinuousQueryMessageProducer(testCQDistributedMap3(), + "surname=TestSurname2"); + producer.setOutputChannel(cqDistributedMapChannel3()); + producer.setCacheEventTypes("UPDATED"); + producer.setIncludeValue(false); + return producer; + } + + @Bean + public HazelcastClusterMonitorMessageProducer hazelcastClusterMonitorMessageProducer() { + final HazelcastClusterMonitorMessageProducer producer = + new HazelcastClusterMonitorMessageProducer(testHazelcastInstance()); + producer.setOutputChannel(cmonChannel()); + return producer; + } + + @Bean + public HazelcastClusterMonitorMessageProducer hazelcastClusterMonitorMessageProducer2() { + final HazelcastClusterMonitorMessageProducer producer = + new HazelcastClusterMonitorMessageProducer(testHazelcastInstance()); + producer.setOutputChannel(cmonChannel2()); + producer.setMonitorEventTypes("DISTRIBUTED_OBJECT"); + return producer; + } + + @Bean + @InboundChannelAdapter(value = "dsDistributedMapChannel", + poller = @Poller(maxMessagesPerPoll = "1")) + public HazelcastDistributedSQLMessageSource hazelcastDistributedSQLMessageSource() { + final HazelcastDistributedSQLMessageSource messageSource = + new HazelcastDistributedSQLMessageSource(testDSDistributedMap(), + "name='TestName4' AND surname='TestSurname4'"); + messageSource.setIterationType(DistributedSQLIterationType.ENTRY); + return messageSource; + } + + @Bean + @InboundChannelAdapter(value = "dsDistributedMapChannel2", + poller = @Poller(maxMessagesPerPoll = "1")) + public HazelcastDistributedSQLMessageSource hazelcastDistributedSQLMessageSource2() { + final HazelcastDistributedSQLMessageSource messageSource = + new HazelcastDistributedSQLMessageSource(testDSDistributedMap2(), + "name='TestName1' AND surname='TestSurname1'"); + messageSource.setIterationType(DistributedSQLIterationType.KEY); + return messageSource; + } + + @Bean + @InboundChannelAdapter(value = "dsDistributedMapChannel3", + poller = @Poller(maxMessagesPerPoll = "1")) + public HazelcastDistributedSQLMessageSource hazelcastDistributedSQLMessageSource3() { + final HazelcastDistributedSQLMessageSource messageSource = + new HazelcastDistributedSQLMessageSource(testDSDistributedMap3(), + "age > 5"); + messageSource.setIterationType(DistributedSQLIterationType.KEY); + return messageSource; + } + + @Bean + @InboundChannelAdapter(value = "dsDistributedMapChannel4", + poller = @Poller(maxMessagesPerPoll = "1")) + public HazelcastDistributedSQLMessageSource hazelcastDistributedSQLMessageSource4() { + final HazelcastDistributedSQLMessageSource messageSource = + new HazelcastDistributedSQLMessageSource(testDSDistributedMap4(), + "name='TestName3' AND surname='TestSurname3'"); + messageSource.setIterationType(DistributedSQLIterationType.VALUE); + return messageSource; + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/util/HazelcastInboundChannelAdapterTestUtils.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/util/HazelcastInboundChannelAdapterTestUtils.java new file mode 100644 index 0000000000..9b2227a4a4 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/inbound/util/HazelcastInboundChannelAdapterTestUtils.java @@ -0,0 +1,370 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.inbound.util; + +import java.util.Collection; +import java.util.Map; + +import com.hazelcast.cluster.MembershipEvent; +import com.hazelcast.collection.ICollection; +import com.hazelcast.core.DistributedObjectEvent; +import com.hazelcast.core.EntryEventType; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.map.IMap; +import com.hazelcast.multimap.MultiMap; +import com.hazelcast.replicatedmap.ReplicatedMap; +import com.hazelcast.spi.exception.DistributedObjectDestroyedException; +import com.hazelcast.topic.ITopic; + +import org.springframework.integration.hazelcast.HazelcastHeaders; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.message.EntryEventMessagePayload; +import org.springframework.messaging.Message; +import org.springframework.messaging.PollableChannel; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +/** + * Util Class for Hazelcast Inbound Channel Adapters Test Support. + * + * @author Eren Avsarogullari + * @since 6.0 + */ +@SuppressWarnings("unchecked") +public final class HazelcastInboundChannelAdapterTestUtils { + + public static final int TIMEOUT = 30_000; + + public static void verifyEntryEvent(Message msg, String cacheName, + EntryEventType event) { + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + if (event == EntryEventType.CLEAR_ALL || event == EntryEventType.EVICT_ALL) { + assertThat(msg.getPayload() instanceof Integer).isTrue(); + } + else { + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + } + + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo(cacheName); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(event.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + } + + public static void verifyItemEvent(Message msg, EntryEventType event) { + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE).toString()).isEqualTo(event.toString()); + } + + public static void testEventDrivenForADDEDDistributedMapEntryEvent( + final IMap distributedMap, + final PollableChannel channel, final String cacheName) { + HazelcastIntegrationTestUser hazelcastIntegrationTestUser = + new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1"); + distributedMap.put(1, hazelcastIntegrationTestUser); + Message msg = channel.receive(TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(EntryEventType.ADDED.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo(cacheName); + + assertThat(((EntryEventMessagePayload) msg + .getPayload()).key).isEqualTo(Integer.valueOf(1)); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getId()).isEqualTo(1); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getName()).isEqualTo("TestName1"); + assertThat((((EntryEventMessagePayload) msg + .getPayload()).value).getSurname()).isEqualTo("TestSurname1"); + } + + public static void testEventDrivenForDistributedMapEntryEvents( + final IMap distributedMap, + final PollableChannel channel, final String cacheName) { + distributedMap + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + Message msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.ADDED); + + distributedMap.put(1, + new HazelcastIntegrationTestUser(1, "TestName1", "TestSurnameUpdated")); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.UPDATED); + + distributedMap.remove(1); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.REMOVED); + + distributedMap + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2")); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.ADDED); + + distributedMap.clear(); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.CLEAR_ALL); + } + + public static void testEventDrivenForDistributedCollectionItemEvents( + final ICollection distributedObject, + final PollableChannel channel) { + HazelcastIntegrationTestUser user = + new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1"); + distributedObject.add(user); + Message msg = channel.receive(TIMEOUT); + verifyItemEvent(msg, EntryEventType.ADDED); + + distributedObject.remove(user); + msg = channel.receive(TIMEOUT); + verifyItemEvent(msg, EntryEventType.REMOVED); + + user = new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2"); + distributedObject.add(user); + msg = channel.receive(TIMEOUT); + verifyItemEvent(msg, EntryEventType.ADDED); + } + + public static void testEventDrivenForReplicatedMapEntryEvents( + final ReplicatedMap replicatedMap, + final PollableChannel channel, final String cacheName) { + replicatedMap + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + Message msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.ADDED); + + replicatedMap.put(1, + new HazelcastIntegrationTestUser(1, "TestName1", "TestSurnameUpdated")); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.UPDATED); + + replicatedMap.remove(1); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.REMOVED); + + replicatedMap + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2")); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.ADDED); + } + + public static void testEventDrivenForTopicMessageEvent( + final ITopic topic, final PollableChannel channel) { + topic.publish(new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + Message msg = channel.receive(TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.PUBLISHING_TIME)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo(topic.getName()); + assertThat(((HazelcastIntegrationTestUser) msg.getPayload()).getId()).isEqualTo(1); + assertThat(((HazelcastIntegrationTestUser) msg.getPayload()).getName()).isEqualTo("TestName1"); + assertThat(((HazelcastIntegrationTestUser) msg.getPayload()).getSurname()).isEqualTo("TestSurname1"); + } + + public static void testEventDrivenForMultiMapEntryEvents( + final MultiMap multiMap, + final PollableChannel channel, final String cacheName) { + multiMap.put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + Message msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.ADDED); + + multiMap.put(1, + new HazelcastIntegrationTestUser(1, "TestName1", "TestSurnameUpdated")); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.ADDED); + + multiMap.remove(1); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.REMOVED); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.REMOVED); + + multiMap.put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2")); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.ADDED); + + multiMap.clear(); + msg = channel.receive(TIMEOUT); + verifyEntryEvent(msg, cacheName, EntryEventType.CLEAR_ALL); + } + + public static void testContinuousQueryForUPDATEDEntryEventWhenIncludeValueIsFalse( + final IMap cqDistributedMap, + final PollableChannel channel, final String cacheName) { + cqDistributedMap + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1")); + cqDistributedMap + .put(1, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2")); + Message msg = channel.receive(TIMEOUT); + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof EntryEventMessagePayload).isTrue(); + assertThat(msg.getHeaders().get(HazelcastHeaders.MEMBER)).isNotNull(); + assertThat(msg.getHeaders().get(HazelcastHeaders.EVENT_TYPE)).isEqualTo(EntryEventType.UPDATED.name()); + assertThat(msg.getHeaders().get(HazelcastHeaders.CACHE_NAME)).isEqualTo(cacheName); + + assertThat(((EntryEventMessagePayload) msg + .getPayload()).key).isEqualTo(Integer.valueOf(1)); + assertThat(((EntryEventMessagePayload) msg + .getPayload()).oldValue).isNull(); + assertThat(((EntryEventMessagePayload) msg + .getPayload()).value).isNull(); + } + + public static void testDistributedSQLForENTRYIterationType( + final IMap dsDistributedMap, + final PollableChannel channel) { + dsDistributedMap + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1", 10)); + dsDistributedMap + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2", 20)); + dsDistributedMap + .put(3, new HazelcastIntegrationTestUser(3, "TestName3", "TestSurname3", 30)); + dsDistributedMap + .put(4, new HazelcastIntegrationTestUser(4, "TestName4", "TestSurname4", 40)); + dsDistributedMap + .put(5, new HazelcastIntegrationTestUser(5, "TestName5", "TestSurname5", 50)); + + Message msg = channel.receive(TIMEOUT); + + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof Collection).isTrue(); + assertThat((((Map.Entry) ((Collection) msg.getPayload()).iterator().next()) + .getKey())).isEqualTo(4); + assertThat(((HazelcastIntegrationTestUser) ((Map.Entry) ((Collection) msg + .getPayload()).iterator().next()).getValue()).getId()).isEqualTo(4); + assertThat(((HazelcastIntegrationTestUser) ((Map.Entry) ((Collection) msg + .getPayload()).iterator().next()).getValue()).getName()).isEqualTo("TestName4"); + assertThat(((HazelcastIntegrationTestUser) ((Map.Entry) ((Collection) msg + .getPayload()).iterator().next()).getValue()).getSurname()).isEqualTo("TestSurname4"); + } + + public static void testDistributedSQLForKEYIterationType( + final IMap dsDistributedMap, + final PollableChannel channel) { + dsDistributedMap + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1", 10)); + dsDistributedMap + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2", 20)); + dsDistributedMap + .put(3, new HazelcastIntegrationTestUser(3, "TestName3", "TestSurname3", 30)); + + Message msg = channel.receive(TIMEOUT); + + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof Collection).isTrue(); + assertThat(((Collection) msg.getPayload()).iterator().next()).isEqualTo(1); + } + + public static void testDistributedSQLForLOCAL_KEYIterationType( + final IMap dsDistributedMap, + final PollableChannel channel) { + dsDistributedMap + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1", 10)); + dsDistributedMap + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2", 20)); + dsDistributedMap + .put(3, new HazelcastIntegrationTestUser(3, "TestName3", "TestSurname3", 30)); + + Message msg = channel.receive(TIMEOUT); + + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof Collection).isTrue(); + } + + public static void testDistributedSQLForVALUEIterationType( + final IMap dsDistributedMap, + final PollableChannel channel) { + dsDistributedMap + .put(1, new HazelcastIntegrationTestUser(1, "TestName1", "TestSurname1", 10)); + dsDistributedMap + .put(2, new HazelcastIntegrationTestUser(2, "TestName2", "TestSurname2", 20)); + dsDistributedMap + .put(3, new HazelcastIntegrationTestUser(3, "TestName3", "TestSurname3", 30)); + dsDistributedMap + .put(4, new HazelcastIntegrationTestUser(4, "TestName4", "TestSurname4", 40)); + dsDistributedMap + .put(5, new HazelcastIntegrationTestUser(5, "TestName5", "TestSurname5", 50)); + + Message msg = channel.receive(TIMEOUT); + + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof Collection).isTrue(); + assertThat(((HazelcastIntegrationTestUser) (((Collection) msg.getPayload()).iterator() + .next())).getId()).isEqualTo(3); + assertThat(((HazelcastIntegrationTestUser) (((Collection) msg.getPayload()).iterator() + .next())).getName()).isEqualTo("TestName3"); + assertThat(((HazelcastIntegrationTestUser) (((Collection) msg.getPayload()).iterator() + .next())).getSurname()).isEqualTo("TestSurname3"); + } + + public static void testDistributedObjectEventByChannelAndHazelcastInstance( + final PollableChannel channel, final HazelcastInstance hazelcastInstance, + final String distributedObjectName) { + final IMap distributedMap = + hazelcastInstance.getMap(distributedObjectName); + + Message msg = channel.receive(TIMEOUT); + verifyDistributedObjectEvent(msg, DistributedObjectEvent.EventType.CREATED, + distributedObjectName); + + distributedMap.destroy(); + + msg = channel.receive(TIMEOUT); + try { + // Since Hazelcast 3.6 we can use DistributedObjectEvent.getDistributedObject() for DESTROYED objects. + verifyDistributedObjectEvent(msg, DistributedObjectEvent.EventType.DESTROYED, distributedObjectName); + fail("DistributedObjectDestroyedException expected"); + } + catch (Exception e) { + assertThat(e).isInstanceOf(DistributedObjectDestroyedException.class); + } + } + + private static void verifyMembershipEvent(final Message msg, + final int membershipEvent) { + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof MembershipEvent).isTrue(); + assertThat(((MembershipEvent) msg.getPayload()).getEventType()).isEqualTo(membershipEvent); + assertThat(((MembershipEvent) msg.getPayload()).getMember()).isNotNull(); + } + + private static void verifyDistributedObjectEvent(final Message msg, + final DistributedObjectEvent.EventType eventType, + final String distributedObjectName) { + assertThat(msg).isNotNull(); + assertThat(msg.getPayload()).isNotNull(); + assertThat(msg.getPayload() instanceof DistributedObjectEvent).isTrue(); + assertThat(((DistributedObjectEvent) msg.getPayload()).getEventType()).isEqualTo(eventType); + assertThat(distributedObjectName).as((((DistributedObjectEvent) msg.getPayload()).getDistributedObject()) + .getName()).isNotNull(); + } + + private HazelcastInboundChannelAdapterTestUtils() { + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/leader/LeaderInitiatorTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/leader/LeaderInitiatorTests.java new file mode 100644 index 0000000000..514a8967dc --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/leader/LeaderInitiatorTests.java @@ -0,0 +1,356 @@ +/* + * Copyright 2015-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.leader; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import com.hazelcast.config.Config; +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.cp.CPGroupId; +import com.hazelcast.cp.CPSubsystem; +import com.hazelcast.cp.lock.FencedLock; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.leader.Candidate; +import org.springframework.integration.leader.Context; +import org.springframework.integration.leader.DefaultCandidate; +import org.springframework.integration.leader.event.AbstractLeaderEvent; +import org.springframework.integration.leader.event.DefaultLeaderEventPublisher; +import org.springframework.integration.leader.event.LeaderEventPublisher; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +/** + * Tests for hazelcast leader election. + * + * @author Janne Valkealahti + * @author Patrick Peralta + * @author Dave Syer + * @author Artem Bilan + * @author Mael Le Guével + * @author Emil Palm + */ +@SpringJUnitConfig +@DirtiesContext +public class LeaderInitiatorTests { + + @Autowired + private HazelcastInstance hazelcastInstance; + + @Autowired + private TestCandidate candidate; + + @Autowired + private TestEventListener listener; + + @Autowired + private LeaderInitiator initiator; + + @Test + public void testLeaderElections() throws Exception { + assertThat(this.candidate.onGrantedLatch.await(5, TimeUnit.SECONDS)).isTrue(); + assertThat(this.listener.onEventLatch.await(5, TimeUnit.SECONDS)).isTrue(); + assertThat(this.listener.events.size()).isEqualTo(1); + + this.initiator.destroy(); + + CountDownLatch granted = new CountDownLatch(1); + CountingPublisher countingPublisher = new CountingPublisher(granted); + List initiators = new ArrayList<>(); + for (int i = 0; i < 2; i++) { + LeaderInitiator initiator = new LeaderInitiator(this.hazelcastInstance, new DefaultCandidate()); + initiator.setLeaderEventPublisher(countingPublisher); + initiators.add(initiator); + } + + for (LeaderInitiator initiator : initiators) { + initiator.start(); + } + + assertThat(granted.await(10, TimeUnit.SECONDS)).isTrue(); + + LeaderInitiator initiator1 = countingPublisher.initiator; + + LeaderInitiator initiator2 = null; + + for (LeaderInitiator initiator : initiators) { + if (initiator != initiator1) { + initiator2 = initiator; + break; + } + } + + assertThat(initiator2).isNotNull(); + + assertThat(initiator1.getContext().isLeader()).isTrue(); + assertThat(initiator2.getContext().isLeader()).isFalse(); + + final CountDownLatch granted1 = new CountDownLatch(1); + final CountDownLatch granted2 = new CountDownLatch(1); + CountDownLatch revoked1 = new CountDownLatch(1); + CountDownLatch revoked2 = new CountDownLatch(1); + initiator1.setLeaderEventPublisher(new CountingPublisher(granted1, revoked1) { + + @Override + public void publishOnRevoked(Object source, Context context, String role) { + try { + // It's difficult to see round-robin election, so block one initiator until the second is elected. + assertThat(granted2.await(10, TimeUnit.SECONDS)).isTrue(); + } + catch (InterruptedException e) { + // No op + } + super.publishOnRevoked(source, context, role); + } + + }); + + initiator2.setLeaderEventPublisher(new CountingPublisher(granted2, revoked2) { + + @Override + public void publishOnRevoked(Object source, Context context, String role) { + try { + // It's difficult to see round-robin election, so block one initiator until the second is elected. + assertThat(granted1.await(10, TimeUnit.SECONDS)).isTrue(); + } + catch (InterruptedException e) { + // No op + } + super.publishOnRevoked(source, context, role); + } + + }); + + initiator1.getContext().yield(); + + assertThat(revoked1.await(10, TimeUnit.SECONDS)).isTrue(); + + assertThat(initiator2.getContext().isLeader()).isTrue(); + assertThat(initiator1.getContext().isLeader()).isFalse(); + + initiator2.getContext().yield(); + + assertThat(revoked2.await(10, TimeUnit.SECONDS)).isTrue(); + + assertThat(initiator1.getContext().isLeader()).isTrue(); + assertThat(initiator2.getContext().isLeader()).isFalse(); + + initiator2.destroy(); + + CountDownLatch revoked11 = new CountDownLatch(1); + initiator1.setLeaderEventPublisher(new CountingPublisher(new CountDownLatch(1), revoked11)); + + initiator1.getContext().yield(); + + assertThat(revoked11.await(10, TimeUnit.SECONDS)).isTrue(); + + initiator1.destroy(); + + CountDownLatch onGranted = new CountDownLatch(1); + + DefaultCandidate candidate = spy(new DefaultCandidate()); + willAnswer(invocation -> { + try { + return invocation.callRealMethod(); + } + finally { + onGranted.countDown(); + } + }) + .given(candidate).onGranted(any(Context.class)); + + LeaderInitiator initiator = new LeaderInitiator(this.hazelcastInstance, candidate); + + initiator.setLeaderEventPublisher(new DefaultLeaderEventPublisher() { + + @Override + public void publishOnGranted(Object source, Context context, String role) { + throw new RuntimeException("intentional"); + } + + }); + + initiator.start(); + + assertThat(onGranted.await(5, TimeUnit.SECONDS)).isTrue(); + + assertThat(initiator.getContext().isLeader()).isTrue(); + + initiator.destroy(); + } + + @Test + public void testRevokeLeadershipCalledWhenLockNotAcquiredButStillLeader() throws Exception { + // Initialize mocks and objects needed for the revoke leadership when fenced lock is no longer acquired + HazelcastInstance hazelcastInstance = mock(); + Candidate candidate = mock(); + FencedLock fencedLock = mock(); + LeaderEventPublisher leaderEventPublisher = mock(); + + CPSubsystem cpSubsystem = mock(CPSubsystem.class); + given(candidate.getRole()).willReturn("role"); + given(hazelcastInstance.getCPSubsystem()).willReturn(cpSubsystem); + given(cpSubsystem.getLock(anyString())).willReturn(fencedLock); + given(fencedLock.getGroupId()) + .willReturn(new CPGroupId() { + + @Override + public String getName() { + return ""; + } + + @Override + public long getId() { + return 0; + } + }); + + LeaderInitiator leaderInitiator = new LeaderInitiator(hazelcastInstance, candidate); + leaderInitiator.setLeaderEventPublisher(leaderEventPublisher); + + // Simulate that the lock is currently held by this thread + given(fencedLock.isLockedByCurrentThread()).willReturn(true, false); + given(fencedLock.tryLock(anyLong(), any(TimeUnit.class))).willReturn(false); // Lock acquisition fails + + // Start the LeaderInitiator to trigger the leader election process + leaderInitiator.start(); + + // Simulate the lock acquisition check process + Thread.sleep(1000); // Give time for the async task to run + + // Verify that revokeLeadership was called due to lock not being acquired + // unlock is part of revokeLeadership + verify(fencedLock).unlock(); + // verify revoke event is published + verify(leaderEventPublisher).publishOnRevoked(any(Object.class), any(Context.class), anyString()); + + leaderInitiator.destroy(); + } + + @Configuration + public static class TestConfig { + + @Bean + TestCandidate candidate() { + return new TestCandidate(); + } + + @Bean + Config hazelcastConfig() { + Config config = new Config(); + config.getCPSubsystemConfig() + .setSessionHeartbeatIntervalSeconds(1); + return config; + } + + @Bean(destroyMethod = "shutdown") + HazelcastInstance hazelcastInstance() { + return Hazelcast.newHazelcastInstance(hazelcastConfig()); + } + + @Bean + LeaderInitiator initiator() { + return new LeaderInitiator(hazelcastInstance(), candidate()); + } + + @Bean + TestEventListener testEventListener() { + return new TestEventListener(); + } + + } + + static class TestCandidate extends DefaultCandidate { + + CountDownLatch onGrantedLatch = new CountDownLatch(1); + + @Override + public void onGranted(Context ctx) { + this.onGrantedLatch.countDown(); + super.onGranted(ctx); + } + + } + + static class TestEventListener implements ApplicationListener { + + CountDownLatch onEventLatch = new CountDownLatch(1); + + ArrayList events = new ArrayList<>(); + + @Override + public void onApplicationEvent(AbstractLeaderEvent event) { + this.events.add(event); + this.onEventLatch.countDown(); + } + + } + + private static class CountingPublisher implements LeaderEventPublisher { + + private CountDownLatch granted; + + private CountDownLatch revoked; + + private volatile LeaderInitiator initiator; + + CountingPublisher(CountDownLatch granted, CountDownLatch revoked) { + this.granted = granted; + this.revoked = revoked; + } + + CountingPublisher(CountDownLatch granted) { + this(granted, new CountDownLatch(1)); + } + + @Override + public void publishOnRevoked(Object source, Context context, String role) { + this.revoked.countDown(); + } + + @Override + public void publishOnFailedToAcquire(Object source, Context context, String role) { + + } + + @Override + public void publishOnGranted(Object source, Context context, String role) { + this.initiator = (LeaderInitiator) source; + this.granted.countDown(); + } + + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/lock/HazelcastLockRegistryTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/lock/HazelcastLockRegistryTests.java new file mode 100644 index 0000000000..21346f39fd --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/lock/HazelcastLockRegistryTests.java @@ -0,0 +1,284 @@ +/* + * Copyright 2017-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.lock; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; + +import com.hazelcast.config.Config; +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.cp.lock.FencedLock; +import com.hazelcast.instance.impl.HazelcastInstanceFactory; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Artem Bilan + */ +public class HazelcastLockRegistryTests { + + private static final Config CONFIG = new Config(); + + static { + CONFIG.getCPSubsystemConfig().setCPMemberCount(0); + } + + private static final HazelcastInstance instance = Hazelcast.newHazelcastInstance(CONFIG); + + @AfterAll + public static void destroy() { + HazelcastInstanceFactory.terminateAll(); + } + + @Test + public void testLock() { + HazelcastLockRegistry registry = new HazelcastLockRegistry(instance); + for (int i = 0; i < 10; i++) { + Lock lock = registry.obtain("foo"); + lock.lock(); + try { + assertThat(((FencedLock) lock).isLocked()).isTrue(); + assertThat(((FencedLock) lock).isLockedByCurrentThread()).isTrue(); + } + finally { + lock.unlock(); + } + } + } + + @Test + public void testLockInterruptibly() throws Exception { + HazelcastLockRegistry registry = new HazelcastLockRegistry(instance); + for (int i = 0; i < 10; i++) { + Lock lock = registry.obtain("foo"); + lock.lockInterruptibly(); + try { + assertThat(((FencedLock) lock).isLocked()).isTrue(); + assertThat(((FencedLock) lock).isLockedByCurrentThread()).isTrue(); + } + finally { + lock.unlock(); + } + } + } + + @Test + public void testReentrantLock() { + HazelcastLockRegistry registry = new HazelcastLockRegistry(instance); + for (int i = 0; i < 10; i++) { + Lock lock1 = registry.obtain("foo"); + lock1.lock(); + try { + Lock lock2 = registry.obtain("foo"); + assertThat(lock2).isSameAs(lock1); + lock2.lock(); + lock2.unlock(); + } + finally { + lock1.unlock(); + } + } + } + + @Test + public void testReentrantLockInterruptibly() throws Exception { + HazelcastLockRegistry registry = new HazelcastLockRegistry(instance); + for (int i = 0; i < 10; i++) { + Lock lock1 = registry.obtain("foo"); + lock1.lockInterruptibly(); + try { + Lock lock2 = registry.obtain("foo"); + assertThat(lock2).isSameAs(lock1); + lock2.lockInterruptibly(); + lock2.unlock(); + } + finally { + lock1.unlock(); + } + } + } + + @Test + public void testTwoLocks() throws Exception { + HazelcastLockRegistry registry = new HazelcastLockRegistry(instance); + for (int i = 0; i < 10; i++) { + Lock lock1 = registry.obtain("foo"); + lock1.lockInterruptibly(); + try { + Lock lock2 = registry.obtain("bar"); + assertThat(lock2).isNotSameAs(lock1); + lock2.lockInterruptibly(); + lock2.unlock(); + } + finally { + lock1.unlock(); + } + } + } + + @Test + public void testTwoThreadsSecondFailsToGetLock() throws Exception { + HazelcastLockRegistry registry = new HazelcastLockRegistry(instance); + Lock lock1 = registry.obtain("foo"); + lock1.lockInterruptibly(); + AtomicBoolean locked = new AtomicBoolean(); + CountDownLatch latch = new CountDownLatch(1); + ExecutorService executorService = Executors.newSingleThreadExecutor(); + Future result = executorService.submit(() -> { + Lock lock2 = registry.obtain("foo"); + locked.set(lock2.tryLock(200, TimeUnit.MILLISECONDS)); + latch.countDown(); + try { + lock2.unlock(); + } + catch (Exception e) { + return e; + } + return null; + }); + assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue(); + assertThat(locked.get()).isFalse(); + lock1.unlock(); + Object ise = result.get(10, TimeUnit.SECONDS); + assertThat(ise).isInstanceOf(IllegalMonitorStateException.class); + assertThat(((Exception) ise).getMessage()).contains("Current thread is not owner of the lock!"); + executorService.shutdown(); + } + + @Test + public void testTwoThreads() throws Exception { + HazelcastLockRegistry registry = new HazelcastLockRegistry(instance); + Lock lock1 = registry.obtain("foo"); + AtomicBoolean locked = new AtomicBoolean(); + CountDownLatch latch1 = new CountDownLatch(1); + CountDownLatch latch2 = new CountDownLatch(1); + CountDownLatch latch3 = new CountDownLatch(1); + lock1.lockInterruptibly(); + ExecutorService executorService = Executors.newSingleThreadExecutor(); + executorService.execute(() -> { + Lock lock2 = registry.obtain("foo"); + try { + latch1.countDown(); + lock2.lockInterruptibly(); + latch2.await(10, TimeUnit.SECONDS); + locked.set(true); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + finally { + lock2.unlock(); + latch3.countDown(); + } + }); + assertThat(latch1.await(10, TimeUnit.SECONDS)).isTrue(); + assertThat(locked.get()).isFalse(); + lock1.unlock(); + latch2.countDown(); + assertThat(latch3.await(10, TimeUnit.SECONDS)).isTrue(); + assertThat(locked.get()).isTrue(); + executorService.shutdown(); + } + + @Test + public void testTwoThreadsDifferentRegistries() throws Exception { + HazelcastLockRegistry registry1 = new HazelcastLockRegistry(instance); + HazelcastLockRegistry registry2 = new HazelcastLockRegistry(instance); + Lock lock1 = registry1.obtain("foo"); + AtomicBoolean locked = new AtomicBoolean(); + CountDownLatch latch1 = new CountDownLatch(1); + CountDownLatch latch2 = new CountDownLatch(1); + CountDownLatch latch3 = new CountDownLatch(1); + lock1.lockInterruptibly(); + ExecutorService executorService = Executors.newSingleThreadExecutor(); + executorService.execute(() -> { + Lock lock2 = registry2.obtain("foo"); + try { + latch1.countDown(); + lock2.lockInterruptibly(); + latch2.await(10, TimeUnit.SECONDS); + locked.set(true); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + finally { + lock2.unlock(); + latch3.countDown(); + } + }); + assertThat(latch1.await(10, TimeUnit.SECONDS)).isTrue(); + assertThat(locked.get()).isFalse(); + lock1.unlock(); + latch2.countDown(); + assertThat(latch3.await(10, TimeUnit.SECONDS)).isTrue(); + assertThat(locked.get()).isTrue(); + executorService.shutdown(); + } + + @Test + public void testTwoThreadsWrongOneUnlocks() throws Exception { + HazelcastLockRegistry registry = new HazelcastLockRegistry(instance); + final Lock lock = registry.obtain("foo"); + lock.lockInterruptibly(); + final AtomicBoolean locked = new AtomicBoolean(); + final CountDownLatch latch = new CountDownLatch(1); + ExecutorService executorService = Executors.newSingleThreadExecutor(); + Future result = executorService.submit(() -> { + try { + lock.unlock(); + } + catch (Exception e) { + latch.countDown(); + return e; + } + return null; + }); + assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue(); + assertThat(locked.get()).isFalse(); + lock.unlock(); + Object imse = result.get(10, TimeUnit.SECONDS); + assertThat(imse).isInstanceOf(IllegalMonitorStateException.class); + assertThat(((Exception) imse).getMessage()).contains("Current thread is not owner of the lock!"); + executorService.shutdown(); + } + + @Test + public void testTryLock() throws Exception { + HazelcastLockRegistry registry = new HazelcastLockRegistry(instance); + for (int i = 0; i < 10; i++) { + Lock lock = registry.obtain("foo"); + + int n = 0; + while (!lock.tryLock() && n++ < 100) { + Thread.sleep(100); + } + assertThat(n).isLessThan(100); + + lock.unlock(); + } + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/metadata/HazelcastMetadataStoreTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/metadata/HazelcastMetadataStoreTests.java new file mode 100644 index 0000000000..0af926b169 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/metadata/HazelcastMetadataStoreTests.java @@ -0,0 +1,163 @@ +/* + * Copyright 2017-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.metadata; + +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.map.IMap; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.springframework.integration.metadata.MetadataStoreListener; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.awaitility.Awaitility.await; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * @author Vinicius Carvalho + * @author Artem Bilan + */ +public class HazelcastMetadataStoreTests { + + private static HazelcastInstance instance; + + private static IMap map; + + HazelcastMetadataStore metadataStore; + + @BeforeAll + public static void init() { + instance = Hazelcast.newHazelcastInstance(); + map = instance.getMap("customTestsMetadataStore"); + } + + @AfterAll + public static void destroy() { + instance.shutdown(); + } + + @BeforeEach + public void setup() { + this.metadataStore = new HazelcastMetadataStore(map); + this.metadataStore.afterPropertiesSet(); + } + + @AfterEach + public void clean() { + map.clear(); + } + + @Test + public void testGetNonExistingKeyValue() { + String retrievedValue = this.metadataStore.get("does-not-exist"); + assertThat(retrievedValue).isNull(); + } + + @Test + public void testPersistKeyValue() { + this.metadataStore.put("HazelcastMetadataStoreTests-Spring", "Integration"); + assertThat(map.get("HazelcastMetadataStoreTests-Spring")).isEqualTo("Integration"); + } + + @Test + public void testGetValueFromMetadataStore() { + this.metadataStore.put("HazelcastMetadataStoreTests-GetValue", "Hello Hazelcast"); + String retrievedValue = this.metadataStore.get("HazelcastMetadataStoreTests-GetValue"); + assertThat(retrievedValue).isEqualTo("Hello Hazelcast"); + } + + @Test + public void testPersistEmptyStringToMetadataStore() { + this.metadataStore.put("HazelcastMetadataStoreTests-PersistEmpty", ""); + String retrievedValue = this.metadataStore.get("HazelcastMetadataStoreTests-PersistEmpty"); + assertThat(retrievedValue).isEqualTo(""); + } + + @Test + public void testPersistNullStringToMetadataStore() { + assertThatIllegalArgumentException() + .isThrownBy(() -> this.metadataStore.put("HazelcastMetadataStoreTests-PersistEmpty", null)) + .withMessage("'value' must not be null."); + } + + @Test + public void testPersistWithEmptyKeyToMetadataStore() { + this.metadataStore.put("", "PersistWithEmptyKey"); + String retrievedValue = this.metadataStore.get(""); + assertThat(retrievedValue).isEqualTo("PersistWithEmptyKey"); + } + + @Test + public void testPersistWithNullKeyToMetadataStore() { + assertThatIllegalArgumentException() + .isThrownBy(() -> this.metadataStore.put(null, "something")) + .withMessage("'key' must not be null."); + } + + @Test + public void testGetValueWithNullKeyFromMetadataStore() { + assertThatIllegalArgumentException() + .isThrownBy(() -> this.metadataStore.get(null)) + .withMessage("'key' must not be null."); + } + + @Test + public void testRemoveFromMetadataStore() { + String testKey = "HazelcastMetadataStoreTests-Remove"; + String testValue = "Integration"; + + this.metadataStore.put(testKey, testValue); + + assertThat(this.metadataStore.remove(testKey)).isEqualTo(testValue); + assertThat(this.metadataStore.remove(testKey)).isNull(); + } + + @Test + public void testPersistKeyValueIfAbsent() { + this.metadataStore.putIfAbsent("HazelcastMetadataStoreTests-Spring", "Integration"); + assertThat(map.get("HazelcastMetadataStoreTests-Spring")).isEqualTo("Integration"); + } + + @Test + public void testReplaceValue() { + this.metadataStore.put("key", "old"); + assertThat(map.get("key")).isEqualTo("old"); + this.metadataStore.replace("key", "old", "new"); + assertThat(map.get("key")).isEqualTo("new"); + } + + @Test + public void testListener() { + MetadataStoreListener listener = mock(MetadataStoreListener.class); + this.metadataStore.addListener(listener); + + this.metadataStore.put("foo", "bar"); + this.metadataStore.replace("foo", "bar", "baz"); + this.metadataStore.remove("foo"); + + await().untilAsserted(() -> verify(listener).onAdd("foo", "bar")); + verify(listener).onUpdate("foo", "baz"); + verify(listener).onRemove("foo", "baz"); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/HazelcastOutboundChannelAdapterTests-context.xml b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/HazelcastOutboundChannelAdapterTests-context.xml new file mode 100644 index 0000000000..c1638f0667 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/HazelcastOutboundChannelAdapterTests-context.xml @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/HazelcastOutboundChannelAdapterTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/HazelcastOutboundChannelAdapterTests.java new file mode 100644 index 0000000000..7ad7bac317 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/HazelcastOutboundChannelAdapterTests.java @@ -0,0 +1,471 @@ +/* + * Copyright 2015-2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.outbound; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Queue; +import java.util.Set; +import java.util.TreeMap; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.TimeUnit; + +import com.hazelcast.instance.impl.HazelcastInstanceFactory; +import com.hazelcast.multimap.MultiMap; +import com.hazelcast.replicatedmap.ReplicatedMap; +import com.hazelcast.topic.ITopic; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.integration.hazelcast.HazelcastHeaders; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.HazelcastTestRequestHandlerAdvice; +import org.springframework.integration.hazelcast.outbound.util.HazelcastOutboundChannelAdapterTestUtils; +import org.springframework.integration.support.DefaultMessageBuilderFactory; +import org.springframework.integration.support.MessageBuilderFactory; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHandlingException; +import org.springframework.messaging.support.GenericMessage; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +/** + * Hazelcast Outbound Channel Adapter Test Class. + * + * @author Eren Avsarogullari + * @author Artem Bilan + * + * @since 6.0 + */ +@SpringJUnitConfig +@DirtiesContext +@SuppressWarnings({"unchecked", "rawtypes"}) +public class HazelcastOutboundChannelAdapterTests { + + private static final String DISTRIBUTED_MAP = "distributedMap"; + + private static final String CACHE_HEADER = "CACHE_HEADER"; + + private final MessageBuilderFactory messageBuilderFactory = + new DefaultMessageBuilderFactory(); + + @Autowired + @Qualifier("firstMapChannel") + private MessageChannel firstMapChannel; + + @Autowired + @Qualifier("secondMapChannel") + private MessageChannel secondMapChannel; + + @Autowired + @Qualifier("thirdMapChannel") + private MessageChannel thirdMapChannel; + + @Autowired + @Qualifier("fourthMapChannel") + private MessageChannel fourthMapChannel; + + @Autowired + @Qualifier("fifthMapChannel") + private MessageChannel fifthMapChannel; + + @Autowired + @Qualifier("sixthMapChannel") + private MessageChannel sixthMapChannel; + + @Autowired + @Qualifier("bulkMapChannel") + private MessageChannel bulkMapChannel; + + @Autowired + @Qualifier("multiMapChannel") + private MessageChannel multiMapChannel; + + @Autowired + @Qualifier("replicatedMapChannel") + private MessageChannel replicatedMapChannel; + + @Autowired + @Qualifier("bulkReplicatedMapChannel") + private MessageChannel bulkReplicatedMapChannel; + + @Autowired + @Qualifier("listChannel") + private MessageChannel listChannel; + + @Autowired + @Qualifier("bulkListChannel") + private MessageChannel bulkListChannel; + + @Autowired + @Qualifier("setChannel") + private MessageChannel setChannel; + + @Autowired + @Qualifier("bulkSetChannel") + private MessageChannel bulkSetChannel; + + @Autowired + @Qualifier("queueChannel") + private MessageChannel queueChannel; + + @Autowired + @Qualifier("bulkQueueChannel") + private MessageChannel bulkQueueChannel; + + @Autowired + @Qualifier("topicChannel") + private MessageChannel topicChannel; + + @Autowired + @Qualifier("lockChannel") + private MessageChannel lockChannel; + + @Autowired + private Map distributedMap; + + @Autowired + private Map distributedBulkMap; + + @Autowired + private MultiMap multiMap; + + @Autowired + private ReplicatedMap replicatedMap; + + @Autowired + private ReplicatedMap bulkReplicatedMap; + + @Autowired + private List distributedList; + + @Autowired + private List distributedBulkList; + + @Autowired + private Set distributedSet; + + @Autowired + private Set distributedBulkSet; + + @Autowired + private Queue distributedQueue; + + @Autowired + private Queue distributedBulkQueue; + + @Autowired + private ITopic topic; + + @Autowired + @Qualifier("testFirstMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testFirstMapRequestHandlerAdvice; + + @Autowired + @Qualifier("testSecondMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testSecondMapRequestHandlerAdvice; + + @Autowired + @Qualifier("testThirdMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testThirdMapRequestHandlerAdvice; + + @Autowired + @Qualifier("testFourthMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testFourthMapRequestHandlerAdvice; + + @Autowired + @Qualifier("testBulkMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testBulkMapRequestHandlerAdvice; + + @Autowired + @Qualifier("testMultiMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testMultiMapRequestHandlerAdvice; + + @Autowired + @Qualifier("testReplicatedMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testReplicatedMapRequestHandlerAdvice; + + @Autowired + @Qualifier("testBulkReplicatedMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testBulkReplicatedMapRequestHandlerAdvice; + + @Autowired + @Qualifier("testListRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testListRequestHandlerAdvice; + + @Autowired + @Qualifier("testBulkListRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testBulkListRequestHandlerAdvice; + + @Autowired + @Qualifier("testSetRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testSetRequestHandlerAdvice; + + @Autowired + @Qualifier("testBulkSetRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testBulkSetRequestHandlerAdvice; + + @Autowired + @Qualifier("testQueueRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testQueueRequestHandlerAdvice; + + @Autowired + @Qualifier("testBulkQueueRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testBulkQueueRequestHandlerAdvice; + + @Autowired + @Qualifier("testTopicRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice testTopicRequestHandlerAdvice; + + @AfterAll + public static void shutdown() { + HazelcastInstanceFactory.terminateAll(); + } + + @BeforeEach + public void setUp() { + this.distributedMap.clear(); + this.distributedBulkMap.clear(); + this.distributedList.clear(); + this.distributedBulkList.clear(); + this.distributedSet.clear(); + this.distributedBulkSet.clear(); + this.distributedQueue.clear(); + this.distributedBulkQueue.clear(); + this.multiMap.clear(); + this.replicatedMap.clear(); + this.bulkReplicatedMap.clear(); + } + + @Test + public void testWriteToDistributedMap() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToDistributedMap(this.firstMapChannel, this.distributedMap, + this.testFirstMapRequestHandlerAdvice); + } + + @Test + public void testBulkWriteToDistributedMap() { + HazelcastOutboundChannelAdapterTestUtils + .testBulkWriteToDistributedMap(this.bulkMapChannel, this.distributedBulkMap, + this.testBulkMapRequestHandlerAdvice); + } + + @Test + public void testWriteToDistributedMapWhenCacheExpressionIsSet() + throws InterruptedException { + sendMessageWithCacheHeaderToChannel(this.secondMapChannel, CACHE_HEADER, + DISTRIBUTED_MAP); + assertThat(this.testSecondMapRequestHandlerAdvice.executeLatch + .await(10, TimeUnit.SECONDS)).isTrue(); + HazelcastOutboundChannelAdapterTestUtils + .verifyMapForPayload(new TreeMap(this.distributedMap)); + } + + @Test + public void testWriteToDistributedMapWhenHazelcastHeaderIsSet() + throws InterruptedException { + sendMessageWithCacheHeaderToChannel(this.thirdMapChannel, + HazelcastHeaders.CACHE_NAME, DISTRIBUTED_MAP); + assertThat(this.testThirdMapRequestHandlerAdvice.executeLatch + .await(10, TimeUnit.SECONDS)).isTrue(); + HazelcastOutboundChannelAdapterTestUtils + .verifyMapForPayload(new TreeMap(this.distributedMap)); + } + + @Test + public void testWriteToDistributedMapWhenExtractPayloadIsFalse() + throws InterruptedException { + sendMessageWithCacheHeaderToChannel(this.fourthMapChannel, + HazelcastHeaders.CACHE_NAME, DISTRIBUTED_MAP); + assertThat(this.testFourthMapRequestHandlerAdvice.executeLatch + .await(10, TimeUnit.SECONDS)).isTrue(); + verifyMapForMessage(new TreeMap(this.distributedMap)); + } + + @Test + public void testWriteToMultiMap() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToMultiMap(this.multiMapChannel, this.multiMap, + this.testMultiMapRequestHandlerAdvice); + } + + @Test + public void testWriteToReplicatedMap() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToReplicatedMap(this.replicatedMapChannel, this.replicatedMap, + this.testReplicatedMapRequestHandlerAdvice); + } + + @Test + public void testBulkWriteToReplicatedMap() throws InterruptedException { + Map userMap = + new HashMap<>(HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + for (int index = 1; index <= HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT; index++) { + userMap.put(index, HazelcastOutboundChannelAdapterTestUtils.getTestUser(index)); + } + + this.bulkReplicatedMapChannel.send(new GenericMessage<>(userMap)); + + assertThat(this.testBulkReplicatedMapRequestHandlerAdvice.executeLatch + .await(10, TimeUnit.SECONDS)).isTrue(); + HazelcastOutboundChannelAdapterTestUtils + .verifyMapForPayload(new TreeMap(this.bulkReplicatedMap)); + } + + @Test + public void testWriteToDistributedList() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToDistributedList(this.listChannel, this.distributedList, + this.testListRequestHandlerAdvice); + } + + @Test + public void testBulkWriteToDistributedList() throws InterruptedException { + List userList = + new ArrayList<>(HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + for (int index = 1; index <= HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT; index++) { + userList.add(HazelcastOutboundChannelAdapterTestUtils.getTestUser(index)); + } + + this.bulkListChannel.send(new GenericMessage<>(userList)); + + assertThat(this.testBulkListRequestHandlerAdvice.executeLatch + .await(10, TimeUnit.SECONDS)).isTrue(); + HazelcastOutboundChannelAdapterTestUtils + .verifyCollection(this.distributedBulkList, + HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + } + + @Test + public void testWriteToDistributedSet() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToDistributedSet(this.setChannel, this.distributedSet, + this.testSetRequestHandlerAdvice); + } + + @Test + public void testBulkWriteToDistributedSet() throws InterruptedException { + Set userSet = + new HashSet<>(HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + for (int index = 1; index <= HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT; index++) { + userSet.add(HazelcastOutboundChannelAdapterTestUtils.getTestUser(index)); + } + + this.bulkSetChannel.send(new GenericMessage<>(userSet)); + + assertThat(this.testBulkSetRequestHandlerAdvice.executeLatch + .await(10, TimeUnit.SECONDS)).isTrue(); + final List list = + new ArrayList(this.distributedBulkSet); + Collections.sort(list); + HazelcastOutboundChannelAdapterTestUtils + .verifyCollection(list, HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + } + + @Test + public void testWriteToDistributedQueue() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToDistributedQueue(this.queueChannel, this.distributedQueue, + this.testQueueRequestHandlerAdvice); + } + + @Test + public void testBulkWriteToDistributedQueue() throws InterruptedException { + Queue userQueue = + new ArrayBlockingQueue(HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + for (int index = 1; index <= HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT; index++) { + userQueue.add(HazelcastOutboundChannelAdapterTestUtils.getTestUser(index)); + } + + this.bulkQueueChannel.send(new GenericMessage<>(userQueue)); + + assertThat(this.testBulkQueueRequestHandlerAdvice.executeLatch + .await(10, TimeUnit.SECONDS)).isTrue(); + HazelcastOutboundChannelAdapterTestUtils + .verifyCollection(this.distributedBulkQueue, + HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + } + + @Test + public void testWriteToTopic() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToTopic(this.topicChannel, this.topic, + this.testTopicRequestHandlerAdvice); + } + + @Test + public void testWriteToDistributedMapWhenCacheIsNotSet() { + assertThatExceptionOfType(MessageHandlingException.class) + .isThrownBy(() -> + this.fifthMapChannel.send( + new GenericMessage<>(HazelcastOutboundChannelAdapterTestUtils.getTestUser(1)))); + } + + @Test + public void testWriteToDistributedMapWhenKeyExpressionIsNotSet() { + Message message = this.messageBuilderFactory + .withPayload(HazelcastOutboundChannelAdapterTestUtils.getTestUser(1)) + .setHeader(HazelcastHeaders.CACHE_NAME, DISTRIBUTED_MAP).build(); + assertThatExceptionOfType(MessageHandlingException.class) + .isThrownBy(() -> this.sixthMapChannel.send(message)); + } + + @Test + public void testWriteToLock() { + assertThatExceptionOfType(MessageHandlingException.class) + .isThrownBy(() -> this.lockChannel.send(new GenericMessage<>("foo"))); + } + + private void sendMessageWithCacheHeaderToChannel(final MessageChannel channel, + final String headerName, final String distributedObjectName) { + + for (int index = 1; index <= HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT; index++) { + Message message = this.messageBuilderFactory + .withPayload(HazelcastOutboundChannelAdapterTestUtils.getTestUser(index)) + .setHeader(headerName, distributedObjectName).build(); + channel.send(message); + } + } + + private static void verifyMapForMessage(final Map> map) { + int index = 1; + assertThat(map).isNotNull(); + assertThat(map.size()).isEqualTo(HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + for (Entry> entry : map.entrySet()) { + assertThat(entry).isNotNull(); + assertThat(entry.getKey().intValue()).isEqualTo(index); + assertThat(entry.getValue().getHeaders().size() > 0).isTrue(); + HazelcastOutboundChannelAdapterTestUtils + .verifyHazelcastIntegrationTestUser(entry.getValue().getPayload(), index); + index++; + } + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/config/HazelcastIntegrationOutboundTestConfiguration.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/config/HazelcastIntegrationOutboundTestConfiguration.java new file mode 100644 index 0000000000..63117ceb59 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/config/HazelcastIntegrationOutboundTestConfiguration.java @@ -0,0 +1,298 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.outbound.config; + +import java.util.List; +import java.util.Queue; +import java.util.Set; + +import com.hazelcast.core.DistributedObject; +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.map.IMap; +import com.hazelcast.multimap.MultiMap; +import com.hazelcast.replicatedmap.ReplicatedMap; +import com.hazelcast.topic.ITopic; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.config.EnableIntegration; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.HazelcastTestRequestHandlerAdvice; +import org.springframework.integration.hazelcast.outbound.HazelcastCacheWritingMessageHandler; +import org.springframework.integration.hazelcast.outbound.util.HazelcastOutboundChannelAdapterTestUtils; +import org.springframework.messaging.MessageChannel; + +/** + * Configuration Class for Hazelcast Integration Outbound Test + * + * @author Eren Avsarogullari + * @author Artem Bilan + * + * @since 6.0 + */ +@Configuration +@EnableIntegration +public class HazelcastIntegrationOutboundTestConfiguration { + + @Bean + public MessageChannel distMapChannel() { + return new DirectChannel(); + } + + @Bean + public MessageChannel distMapBulkChannel() { + return new DirectChannel(); + } + + @Bean + public MessageChannel distListChannel() { + return new DirectChannel(); + } + + @Bean + public MessageChannel distSetChannel() { + return new DirectChannel(); + } + + @Bean + public MessageChannel distQueueChannel() { + return new DirectChannel(); + } + + @Bean + public MessageChannel topicChannel2() { + return new DirectChannel(); + } + + @Bean + public MessageChannel multiMapChannel2() { + return new DirectChannel(); + } + + @Bean + public MessageChannel replicatedMapChannel2() { + return new DirectChannel(); + } + + @Bean + public IMap distMap() { + return testHzInstance().getMap("Distributed_Map1"); + } + + @Bean + public IMap distBulkMap() { + return testHzInstance().getMap("Distributed_Bulk_Map1"); + } + + @Bean + public List distList() { + return testHzInstance().getList("Distributed_List1"); + } + + @Bean + public Set distSet() { + return testHzInstance().getSet("Distributed_Set1"); + } + + @Bean + public Queue distQueue() { + return testHzInstance().getQueue("Distributed_Queue1"); + } + + @Bean + public ITopic topic() { + return testHzInstance().getTopic("Topic1"); + } + + @Bean + public MultiMap multiMap() { + return testHzInstance().getMultiMap("Multi_Map1"); + } + + @Bean + public ReplicatedMap replicatedMap() { + return testHzInstance().getReplicatedMap("Replicated_Map1"); + } + + @Bean(destroyMethod = "shutdown") + public HazelcastInstance testHzInstance() { + return Hazelcast.newHazelcastInstance(); + } + + @Bean + public HazelcastTestRequestHandlerAdvice distMapRequestHandlerAdvice() { + return new HazelcastTestRequestHandlerAdvice( + HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + } + + @Bean + public HazelcastTestRequestHandlerAdvice distBulkMapRequestHandlerAdvice() { + return new HazelcastTestRequestHandlerAdvice(1); + } + + @Bean + public HazelcastTestRequestHandlerAdvice distListRequestHandlerAdvice() { + return new HazelcastTestRequestHandlerAdvice( + HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + } + + @Bean + public HazelcastTestRequestHandlerAdvice distSetRequestHandlerAdvice() { + return new HazelcastTestRequestHandlerAdvice( + HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + } + + @Bean + public HazelcastTestRequestHandlerAdvice distQueueRequestHandlerAdvice() { + return new HazelcastTestRequestHandlerAdvice( + HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + } + + @Bean + public HazelcastTestRequestHandlerAdvice topicRequestHandlerAdvice() { + return new HazelcastTestRequestHandlerAdvice( + HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + } + + @Bean + public HazelcastTestRequestHandlerAdvice multiMapRequestHandlerAdvice() { + return new HazelcastTestRequestHandlerAdvice( + HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + } + + @Bean + public HazelcastTestRequestHandlerAdvice replicatedMapRequestHandlerAdvice() { + return new HazelcastTestRequestHandlerAdvice( + HazelcastOutboundChannelAdapterTestUtils.DATA_COUNT); + } + + @Bean + @ServiceActivator(inputChannel = "distMapChannel", adviceChain = "distMapRequestHandlerAdvice") + public HazelcastCacheWritingMessageHandler hazelcastCacheWritingMessageHandler() { + final HazelcastCacheWritingMessageHandler handler = + new HazelcastCacheWritingMessageHandler(); + handler.setDistributedObject(distMap()); + handler + .setKeyExpression(new SpelExpressionParser().parseExpression("payload.id")); + handler.setExtractPayload(true); + + return handler; + } + + @Bean + @ServiceActivator(inputChannel = "distMapBulkChannel", + adviceChain = "distBulkMapRequestHandlerAdvice") + public HazelcastCacheWritingMessageHandler hazelcastCacheWritingMessageHandler2() { + final HazelcastCacheWritingMessageHandler handler = + new HazelcastCacheWritingMessageHandler(); + handler.setDistributedObject(distBulkMap()); + handler + .setKeyExpression(new SpelExpressionParser().parseExpression("payload.id")); + handler.setExtractPayload(true); + + return handler; + } + + @Bean + @ServiceActivator(inputChannel = "distListChannel", + adviceChain = "distListRequestHandlerAdvice") + public HazelcastCacheWritingMessageHandler hazelcastCacheWritingMessageHandler3() { + final HazelcastCacheWritingMessageHandler handler = + new HazelcastCacheWritingMessageHandler(); + handler.setDistributedObject((DistributedObject) distList()); + handler + .setKeyExpression(new SpelExpressionParser().parseExpression("payload.id")); + handler.setExtractPayload(true); + + return handler; + } + + @Bean + @ServiceActivator(inputChannel = "distSetChannel", + adviceChain = "distSetRequestHandlerAdvice") + public HazelcastCacheWritingMessageHandler hazelcastCacheWritingMessageHandler4() { + final HazelcastCacheWritingMessageHandler handler = + new HazelcastCacheWritingMessageHandler(); + handler.setDistributedObject((DistributedObject) distSet()); + handler + .setKeyExpression(new SpelExpressionParser().parseExpression("payload.id")); + handler.setExtractPayload(true); + + return handler; + } + + @Bean + @ServiceActivator(inputChannel = "distQueueChannel", + adviceChain = "distQueueRequestHandlerAdvice") + public HazelcastCacheWritingMessageHandler hazelcastCacheWritingMessageHandler5() { + final HazelcastCacheWritingMessageHandler handler = + new HazelcastCacheWritingMessageHandler(); + handler.setDistributedObject((DistributedObject) distQueue()); + handler + .setKeyExpression(new SpelExpressionParser().parseExpression("payload.id")); + handler.setExtractPayload(true); + + return handler; + } + + @Bean + @ServiceActivator(inputChannel = "topicChannel2", + adviceChain = "topicRequestHandlerAdvice") + public HazelcastCacheWritingMessageHandler hazelcastCacheWritingMessageHandler6() { + final HazelcastCacheWritingMessageHandler handler = + new HazelcastCacheWritingMessageHandler(); + handler.setDistributedObject(topic()); + handler + .setKeyExpression(new SpelExpressionParser().parseExpression("payload.id")); + handler.setExtractPayload(true); + + return handler; + } + + @Bean + @ServiceActivator(inputChannel = "multiMapChannel2", + adviceChain = "multiMapRequestHandlerAdvice") + public HazelcastCacheWritingMessageHandler hazelcastCacheWritingMessageHandler7() { + final HazelcastCacheWritingMessageHandler handler = + new HazelcastCacheWritingMessageHandler(); + handler.setDistributedObject(multiMap()); + handler + .setKeyExpression(new SpelExpressionParser().parseExpression("payload.id")); + handler.setExtractPayload(true); + + return handler; + } + + @Bean + @ServiceActivator(inputChannel = "replicatedMapChannel2", + adviceChain = "replicatedMapRequestHandlerAdvice") + public HazelcastCacheWritingMessageHandler hazelcastCacheWritingMessageHandler8() { + final HazelcastCacheWritingMessageHandler handler = + new HazelcastCacheWritingMessageHandler(); + handler.setDistributedObject(replicatedMap()); + handler + .setKeyExpression(new SpelExpressionParser().parseExpression("payload.id")); + handler.setExtractPayload(true); + + return handler; + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/config/HazelcastOutboundChannelAdapterConfigTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/config/HazelcastOutboundChannelAdapterConfigTests.java new file mode 100644 index 0000000000..6519363c80 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/config/HazelcastOutboundChannelAdapterConfigTests.java @@ -0,0 +1,200 @@ +/* + * Copyright 2015-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.outbound.config; + +import java.util.List; +import java.util.Queue; +import java.util.Set; + +import com.hazelcast.instance.impl.HazelcastInstanceFactory; +import com.hazelcast.map.IMap; +import com.hazelcast.multimap.MultiMap; +import com.hazelcast.replicatedmap.ReplicatedMap; +import com.hazelcast.topic.ITopic; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.HazelcastTestRequestHandlerAdvice; +import org.springframework.integration.hazelcast.outbound.util.HazelcastOutboundChannelAdapterTestUtils; +import org.springframework.messaging.MessageChannel; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; + +/** + * Hazelcast Outbound Channel Adapter JavaConfig driven Unit Test Class + * + * @author Eren Avsarogullari + * @author Atem Bilan + * + * @since 6.0 + */ +@SpringJUnitConfig(classes = HazelcastIntegrationOutboundTestConfiguration.class) +@DirtiesContext +public class HazelcastOutboundChannelAdapterConfigTests { + + @Autowired + @Qualifier("distMapChannel") + private MessageChannel distMapChannel; + + @Autowired + @Qualifier("distMapBulkChannel") + private MessageChannel distMapBulkChannel; + + @Autowired + @Qualifier("distListChannel") + private MessageChannel distListChannel; + + @Autowired + @Qualifier("distSetChannel") + private MessageChannel distSetChannel; + + @Autowired + @Qualifier("distQueueChannel") + private MessageChannel distQueueChannel; + + @Autowired + @Qualifier("topicChannel2") + private MessageChannel topicChannel2; + + @Autowired + @Qualifier("multiMapChannel2") + private MessageChannel multiMapChannel2; + + @Autowired + @Qualifier("replicatedMapChannel2") + private MessageChannel replicatedMapChannel2; + + @Autowired + private IMap distMap; + + @Autowired + private IMap distBulkMap; + + @Autowired + private List distList; + + @Autowired + private Set distSet; + + @Autowired + private Queue distQueue; + + @Autowired + private ITopic topic; + + @Autowired + private MultiMap multiMap; + + @Autowired + private ReplicatedMap replicatedMap; + + @Autowired + @Qualifier("distMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice distMapRequestHandlerAdvice; + + @Autowired + @Qualifier("distBulkMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice distBulkMapRequestHandlerAdvice; + + @Autowired + @Qualifier("distListRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice distListRequestHandlerAdvice; + + @Autowired + @Qualifier("distSetRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice distSetRequestHandlerAdvice; + + @Autowired + @Qualifier("distQueueRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice distQueueRequestHandlerAdvice; + + @Autowired + @Qualifier("topicRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice topicRequestHandlerAdvice; + + @Autowired + @Qualifier("multiMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice multiMapRequestHandlerAdvice; + + @Autowired + @Qualifier("replicatedMapRequestHandlerAdvice") + private HazelcastTestRequestHandlerAdvice replicatedMapRequestHandlerAdvice; + + @AfterAll + public static void shutdown() { + HazelcastInstanceFactory.terminateAll(); + } + + @Test + public void testWriteToDistributedMap() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToDistributedMap(this.distMapChannel, this.distMap, + this.distMapRequestHandlerAdvice); + } + + @Test + public void testBulkWriteToDistributedMap() { + HazelcastOutboundChannelAdapterTestUtils + .testBulkWriteToDistributedMap(this.distMapBulkChannel, this.distBulkMap, + this.distBulkMapRequestHandlerAdvice); + } + + @Test + public void testWriteToDistributedList() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToDistributedList(this.distListChannel, this.distList, + this.distListRequestHandlerAdvice); + } + + @Test + public void testWriteToDistributedSet() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToDistributedSet(this.distSetChannel, this.distSet, + this.distSetRequestHandlerAdvice); + } + + @Test + public void testWriteToDistributedQueue() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToDistributedQueue(this.distQueueChannel, this.distQueue, + this.distQueueRequestHandlerAdvice); + } + + @Test + public void testWriteToTopic() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToTopic(this.topicChannel2, this.topic, this.topicRequestHandlerAdvice); + } + + @Test + public void testWriteToMultiMap() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToMultiMap(this.multiMapChannel2, this.multiMap, + this.multiMapRequestHandlerAdvice); + } + + @Test + public void testWriteToReplicatedMap() { + HazelcastOutboundChannelAdapterTestUtils + .testWriteToReplicatedMap(this.replicatedMapChannel2, this.replicatedMap, + this.replicatedMapRequestHandlerAdvice); + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/util/HazelcastOutboundChannelAdapterTestUtils.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/util/HazelcastOutboundChannelAdapterTestUtils.java new file mode 100644 index 0000000000..01952c1d41 --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/outbound/util/HazelcastOutboundChannelAdapterTestUtils.java @@ -0,0 +1,248 @@ +/* + * Copyright 2016-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.outbound.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.TimeUnit; + +import com.hazelcast.multimap.MultiMap; +import com.hazelcast.replicatedmap.ReplicatedMap; +import com.hazelcast.topic.ITopic; +import com.hazelcast.topic.MessageListener; + +import org.springframework.integration.hazelcast.HazelcastIntegrationTestUser; +import org.springframework.integration.hazelcast.HazelcastTestRequestHandlerAdvice; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.support.GenericMessage; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; + +/** + * Util Class for Hazelcast Outbound Channel Adapter Test Support + * + * @author Eren Avsarogullari + * + * @since 6.0 + */ +@SuppressWarnings({"unchecked", "rawtypes"}) +public final class HazelcastOutboundChannelAdapterTestUtils { + + public static final int DATA_COUNT = 100; + + public static final int DEFAULT_AGE = 5; + + public static final String TEST_NAME = "Test_Name"; + + public static final String TEST_SURNAME = "Test_Surname"; + + public static void testWriteToDistributedMap(MessageChannel channel, + Map distributedMap, + HazelcastTestRequestHandlerAdvice requestHandlerAdvice) { + testWriteToMap(channel, distributedMap, requestHandlerAdvice); + } + + private static void testWriteToMap(MessageChannel channel, + Map distributedMap, + HazelcastTestRequestHandlerAdvice requestHandlerAdvice) { + try { + sendMessageToChannel(channel); + assertThat(requestHandlerAdvice.executeLatch.await(10, TimeUnit.SECONDS)).isTrue(); + verifyMapForPayload(new TreeMap(distributedMap)); + } + catch (InterruptedException e) { + fail("Test has been failed due to " + e.getMessage()); + } + } + + public static void testBulkWriteToDistributedMap(MessageChannel channel, + Map distributedMap, + HazelcastTestRequestHandlerAdvice requestHandlerAdvice) { + try { + Map userMap = + new HashMap<>(DATA_COUNT); + for (int index = 1; index <= DATA_COUNT; index++) { + userMap.put(index, getTestUser(index)); + } + + channel.send(new GenericMessage<>(userMap)); + + assertThat(requestHandlerAdvice.executeLatch.await(10, TimeUnit.SECONDS)).isTrue(); + verifyMapForPayload(new TreeMap(distributedMap)); + } + catch (InterruptedException e) { + fail("Test has been failed due to " + e.getMessage()); + } + } + + public static void testWriteToMultiMap(MessageChannel channel, + MultiMap multiMap, + HazelcastTestRequestHandlerAdvice requestHandlerAdvice) { + try { + sendMessageToChannel(channel); + assertThat(requestHandlerAdvice.executeLatch.await(10, TimeUnit.SECONDS)).isTrue(); + verifyMultiMapForPayload(multiMap); + } + catch (InterruptedException e) { + fail("Test has been failed due to " + e.getMessage()); + } + } + + public static void testWriteToReplicatedMap(MessageChannel channel, + ReplicatedMap replicatedMap, + HazelcastTestRequestHandlerAdvice requestHandlerAdvice) { + testWriteToMap(channel, replicatedMap, requestHandlerAdvice); + } + + public static void testWriteToDistributedList(MessageChannel channel, + List distributedList, + HazelcastTestRequestHandlerAdvice requestHandlerAdvice) { + testWriteToDistributedCollection(channel, distributedList, requestHandlerAdvice); + } + + private static void testWriteToDistributedCollection(MessageChannel channel, + Collection distributedList, + HazelcastTestRequestHandlerAdvice requestHandlerAdvice) { + try { + sendMessageToChannel(channel); + assertThat(requestHandlerAdvice.executeLatch.await(10, TimeUnit.SECONDS)).isTrue(); + verifyCollection(distributedList, DATA_COUNT); + } + catch (InterruptedException e) { + fail("Test has been failed due to " + e.getMessage()); + } + } + + public static void testWriteToDistributedSet(MessageChannel channel, + Set distributedSet, + HazelcastTestRequestHandlerAdvice requestHandlerAdvice) { + try { + sendMessageToChannel(channel); + assertThat(requestHandlerAdvice.executeLatch.await(10, TimeUnit.SECONDS)).isTrue(); + final List list = new ArrayList(distributedSet); + Collections.sort(list); + verifyCollection(list, DATA_COUNT); + } + catch (InterruptedException e) { + fail("Test has been failed due to " + e.getMessage()); + } + } + + public static void testWriteToDistributedQueue(MessageChannel channel, + Queue distributedQueue, + HazelcastTestRequestHandlerAdvice requestHandlerAdvice) { + testWriteToDistributedCollection(channel, distributedQueue, requestHandlerAdvice); + } + + public static void testWriteToTopic(MessageChannel channel, + ITopic topic, + HazelcastTestRequestHandlerAdvice requestHandlerAdvice) { + try { + topic.addMessageListener(new MessageListener() { + + private int index = 1; + + @Override + public void onMessage(com.hazelcast.topic.Message message) { + HazelcastIntegrationTestUser user = + (HazelcastIntegrationTestUser) message.getMessageObject(); + verifyHazelcastIntegrationTestUser(user, index); + index++; + } + }); + sendMessageToChannel(channel); + assertThat(requestHandlerAdvice.executeLatch.await(10, TimeUnit.SECONDS)).isTrue(); + } + catch (InterruptedException e) { + fail("Test has been failed due to " + e.getMessage()); + } + + } + + public static HazelcastIntegrationTestUser getTestUser(int index) { + return new HazelcastIntegrationTestUser(index, TEST_NAME, TEST_SURNAME, + index + DEFAULT_AGE); + } + + public static void verifyMapForPayload( + final Map map) { + int index = 1; + assertThat(map).isNotNull(); + assertThat(map.size() == DATA_COUNT).isEqualTo(true); + for (Map.Entry entry : map.entrySet()) { + assertThat(entry).isNotNull(); + assertThat(entry.getKey().intValue()).isEqualTo(index); + verifyHazelcastIntegrationTestUser(entry.getValue(), index); + index++; + } + } + + public static void verifyCollection( + final Collection coll, final int dataCount) { + int index = 1; + assertThat(coll).isNotNull(); + assertThat(coll.size() == dataCount).isEqualTo(true); + for (HazelcastIntegrationTestUser user : coll) { + verifyHazelcastIntegrationTestUser(user, index); + index++; + } + } + + public static void verifyHazelcastIntegrationTestUser( + HazelcastIntegrationTestUser user, int index) { + assertThat(user).isNotNull(); + assertThat(user.getId()).isEqualTo(index); + assertThat(user.getName()).isEqualTo(TEST_NAME); + assertThat(user.getSurname()).isEqualTo(TEST_SURNAME); + assertThat(user.getAge()).isEqualTo(index + DEFAULT_AGE); + } + + private static void sendMessageToChannel(final MessageChannel channel) { + for (int index = 1; index <= DATA_COUNT; index++) { + channel.send(new GenericMessage<>(getTestUser(index))); + } + } + + private static void verifyMultiMapForPayload( + final MultiMap multiMap) { + int index = 1; + assertThat(multiMap).isNotNull(); + assertThat(multiMap.size() == DATA_COUNT).isEqualTo(true); + SortedSet keys = new TreeSet<>(multiMap.keySet()); + for (Integer key : keys) { + assertThat(key).isNotNull(); + assertThat(key.intValue()).isEqualTo(index); + HazelcastIntegrationTestUser user = multiMap.get(key).iterator().next(); + verifyHazelcastIntegrationTestUser(user, index); + index++; + } + } + + private HazelcastOutboundChannelAdapterTestUtils() { + } + +} diff --git a/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/store/HazelcastMessageStoreTests.java b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/store/HazelcastMessageStoreTests.java new file mode 100644 index 0000000000..d2b88a377e --- /dev/null +++ b/spring-integration-hazelcast/src/test/java/org/springframework/integration/hazelcast/store/HazelcastMessageStoreTests.java @@ -0,0 +1,176 @@ +/* + * Copyright 2017-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.hazelcast.store; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.map.IMap; +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.integration.channel.DirectChannel; +import org.springframework.integration.history.MessageHistory; +import org.springframework.integration.store.MessageGroup; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.integration.test.util.TestUtils; +import org.springframework.messaging.Message; +import org.springframework.messaging.support.GenericMessage; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Vinicius Carvalho + * @author Artem Bilan + */ +public class HazelcastMessageStoreTests { + + private static HazelcastMessageStore store; + + private static HazelcastInstance instance; + + private static IMap map; + + @BeforeAll + public static void init() { + instance = Hazelcast.newHazelcastInstance(); + map = instance.getMap("customTestsMessageStore"); + store = new HazelcastMessageStore(map); + } + + @AfterAll + public static void destroy() { + instance.shutdown(); + } + + @BeforeEach + public void clean() { + map.clear(); + } + + @Test + public void testWithMessageHistory() { + Message message = new GenericMessage<>("Hello"); + DirectChannel fooChannel = new DirectChannel(); + fooChannel.setBeanName("fooChannel"); + DirectChannel barChannel = new DirectChannel(); + barChannel.setBeanName("barChannel"); + + message = MessageHistory.write(message, fooChannel); + message = MessageHistory.write(message, barChannel); + store.addMessage(message); + message = store.getMessage(message.getHeaders().getId()); + MessageHistory messageHistory = MessageHistory.read(message); + assertThat(messageHistory).isNotNull(); + assertThat(messageHistory.size()).isEqualTo(2); + Properties fooChannelHistory = messageHistory.get(0); + assertThat(fooChannelHistory.get("name")).isEqualTo("fooChannel"); + assertThat(fooChannelHistory.get("type")).isEqualTo("channel"); + + } + + @Test + public void testAddAndRemoveMessagesFromMessageGroup() { + String groupId = "X"; + List> messages = new ArrayList<>(); + for (int i = 0; i < 25; i++) { + Message message = MessageBuilder.withPayload("foo").setCorrelationId(groupId).build(); + store.addMessagesToGroup(groupId, message); + messages.add(message); + } + MessageGroup group = store.getMessageGroup(groupId); + assertThat(group.size()).isEqualTo(25); + store.removeMessagesFromGroup(groupId, messages); + group = store.getMessageGroup(groupId); + assertThat(group.size()).isEqualTo(0); + } + + @Test + public void addAndGetMessage() { + Message message = MessageBuilder.withPayload("test").build(); + store.addMessage(message); + Message retrieved = store.getMessage(message.getHeaders().getId()); + assertThat(retrieved).isEqualTo(message); + } + + @Test + public void customMap() { + assertThat(TestUtils.getPropertyValue(store, "map")).isSameAs(map); + HazelcastMessageStore store2 = new HazelcastMessageStore(instance); + assertThat(TestUtils.getPropertyValue(store2, "map")).isNotSameAs(map); + } + + @Test + public void messageStoreSize() { + Message message1 = MessageBuilder.withPayload("test").build(); + Message message2 = MessageBuilder.withPayload("test").build(); + store.addMessage(message1); + store.addMessage(message2); + long size = store.getMessageCount(); + assertThat(size).isEqualTo(2); + } + + @Test + public void messageStoreIterator() { + Message message1 = MessageBuilder.withPayload("test").build(); + Message message2 = MessageBuilder.withPayload("test").build(); + store.addMessageToGroup("test", message1); + store.addMessageToGroup("test", message2); + int groupCount = 0; + for (MessageGroup messageGroup : store) { + assertThat(messageGroup.size()).isEqualTo(2); + groupCount++; + } + assertThat(groupCount).isEqualTo(1); + } + + @Test + public void sameMessageInTwoGroupsNotRemovedByFirstGroup() { + GenericMessage testMessage = new GenericMessage<>("test data"); + + store.addMessageToGroup("1", testMessage); + store.addMessageToGroup("2", testMessage); + + store.removeMessageGroup("1"); + + assertThat(store.getMessageCount()).isEqualTo(1); + + store.removeMessageGroup("2"); + + assertThat(store.getMessageCount()).isEqualTo(0); + } + + @Test + public void removeMessagesFromGroupDontRemoveSameMessageInOtherGroup() { + GenericMessage testMessage = new GenericMessage<>("test data"); + + store.addMessageToGroup("1", testMessage); + store.addMessageToGroup("2", testMessage); + + store.removeMessagesFromGroup("1", testMessage); + + assertThat(store.getMessageCount()).isEqualTo(1); + assertThat(store.messageGroupSize("1")).isEqualTo(0); + assertThat(store.messageGroupSize("2")).isEqualTo(1); + } + +} diff --git a/spring-integration-hazelcast/src/test/resources/log4j2-test.xml b/spring-integration-hazelcast/src/test/resources/log4j2-test.xml new file mode 100644 index 0000000000..8d9b55201a --- /dev/null +++ b/spring-integration-hazelcast/src/test/resources/log4j2-test.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/reference/antora/modules/ROOT/pages/hazelcast.adoc b/src/reference/antora/modules/ROOT/pages/hazelcast.adoc index 150450ecb2..2736d81c32 100644 --- a/src/reference/antora/modules/ROOT/pages/hazelcast.adoc +++ b/src/reference/antora/modules/ROOT/pages/hazelcast.adoc @@ -1,9 +1,6 @@ [[hazelcast]] = Hazelcast Support -IMPORTANT: This module has been deprecated in version 6.5 and will be removed altogether in 7.0. -Due to Hazelcast migration of many important features, this module depends on, to the https://docs.hazelcast.com/hazelcast/5.5/migrate/community-to-enterprise[Enterprise Edition], we cannot provide an Open Source support here anymore. - Spring Integration provides channel adapters and other utility components to interact with an in-memory data grid https://hazelcast.com[Hazelcast]. You need to include this dependency into your project: