INTEXT-167: Add Cluster Monitor Channel Adapter
JIRA: https://jira.spring.io/browse/INTEXT-167 Some refactorings are done. Hazelcast Cluster Monitor Unit Test Refactorings are done. Some minor bug fixes are done. Redundant assert is removed. HazelcastInstance lifecycle check is added Migration Event UT Case is updated. Code style polishing and upgrade to the `spring.io.plugin-0.4.0`
This commit is contained in:
committed by
Artem Bilan
parent
5c136e45c9
commit
573e1f301f
@@ -6,6 +6,7 @@ The Spring Integration Extensions project provides extension modules for [Spring
|
||||
## Available Modules
|
||||
|
||||
* [Amazon Web Services (AWS)][] Support
|
||||
* [Hazelcast][] Support
|
||||
* [Kafka][] Support
|
||||
* [MQ Telemetry Transport (MQTT)][] Support
|
||||
* [Print][] Support
|
||||
@@ -139,6 +140,7 @@ The Spring Integration Extensions Framework is released under version 2.0 of the
|
||||
[MQ Telemetry Transport]: http://mqtt.org/
|
||||
[Websockets]: http://www.html5rocks.com/en/tutorials/websockets/basics/
|
||||
[XQuery]: http://en.wikipedia.org/wiki/XQuery
|
||||
[Splunk]:http://www.splunk.com/
|
||||
[Splunk]: http://www.splunk.com/
|
||||
[Amazon Web Services (AWS)]: http://aws.amazon.com/
|
||||
[MQ Telemetry Transport (MQTT)]: http://mqtt.org/
|
||||
[Hazelcast]: http://hazelcast.org/
|
||||
|
||||
@@ -28,7 +28,7 @@ Hazelcast Event-Driven Inbound Channel Adapter listens related cache events and
|
||||
```
|
||||
Basically, Hazelcast Event-Driven Inbound Channel Adapter requires following attributes :
|
||||
|
||||
* **channel :** Specifies channel which message is sent. It is mandatory attribute.
|
||||
* **channel :** Specifies channel which message is sent.
|
||||
* **cache :** Specifies the distributed Object reference which is listened. It is mandatory attribute.
|
||||
* **cache-events :** Specifies cache events which are listened. It is optional attribute and its default value is ADDED. Its supported values are as follows :
|
||||
|
||||
@@ -155,7 +155,7 @@ Sample definitions are as follows :
|
||||
|
||||
## HAZELCAST CONTINUOUS QUERY INBOUND CHANNEL ADAPTER
|
||||
|
||||
Hazelcast Continuous Query enables to listen to the modifications performed on specific map entries. Hazelcast Continuous Query Inbound Channel Adapter is an event-driven inbound channel adapter and listens related distributed map events in the light of defined predicate. Its basic definition is as follows :
|
||||
Hazelcast Continuous Query enables to listen to the modifications performed on specific map entries. Hazelcast Continuous Query Inbound Channel Adapter is an event-driven channel adapter and listens to related distributed map events in the light of defined predicate. Its basic definition is as follows :
|
||||
```
|
||||
<int-hazelcast:cq-inbound-channel-adapter
|
||||
channel="cqMapChannel"
|
||||
@@ -167,7 +167,7 @@ Hazelcast Continuous Query enables to listen to the modifications performed on s
|
||||
```
|
||||
Basically, it requires four attributes as follows :
|
||||
|
||||
* **channel :** Specifies channel which message is sent. It is mandatory attribute.
|
||||
* **channel :** Specifies channel which message is sent.
|
||||
* **cache :** Specifies distributed Map reference which is listened. It is mandatory attribute.
|
||||
* **cache-events :** Specifies cache events which are listened. It is optional attribute with ADDED default value. Supported values are ADDED, REMOVED, UPDATED, EVICTED, EVICT_ALL and CLEAR_ALL.
|
||||
* **predicate :** Specifies predicate to listen to the modifications performed on specific map entries. It is mandatory attribute.
|
||||
@@ -200,6 +200,40 @@ Sample definition is as follows :
|
||||
**Reference :** http://docs.hazelcast.org/docs/3.4/manual/html-single/hazelcast-documentation.html#continuous-query
|
||||
|
||||
|
||||
## HAZELCAST CLUSTER MONITOR INBOUND CHANNEL ADAPTER
|
||||
|
||||
Hazelcast Cluster Monitor enables to listen to the modifications performed on cluster. Hazelcast Cluster Monitor Inbound Channel Adapter is an event-driven channel adapter and listens to related Membership, Distributed Object, Migration, Lifecycle and Client events. Its basic definition is as follows :
|
||||
```
|
||||
<int-hazelcast:cm-inbound-channel-adapter
|
||||
channel="monitorChannel"
|
||||
hazelcast-instance="instance"
|
||||
monitor-types="MEMBERSHIP, DISTRIBUTED_OBJECT, MIGRATION, LIFECYCLE, CLIENT" />
|
||||
```
|
||||
Basically, it requires four attributes as follows :
|
||||
|
||||
* **channel :** Specifies channel which message is sent.
|
||||
* **hazelcast-instance :** Specifies Hazelcast Instance reference to listen cluster events. It is mandatory attribute.
|
||||
* **monitor-types :** Specifies monitor types which are listened. It is optional attribute with MEMBERSHIP default value. Supported values are MEMBERSHIP, DISTRIBUTED_OBJECT, MIGRATION, LIFECYCLE, CLIENT.
|
||||
|
||||
Sample definition is as follows :
|
||||
```
|
||||
<int:channel id="monitorChannel"/>
|
||||
|
||||
<int-hazelcast:cm-inbound-channel-adapter
|
||||
channel="monitorChannel"
|
||||
hazelcast-instance="instance"
|
||||
monitor-types="MEMBERSHIP, DISTRIBUTED_OBJECT" />
|
||||
|
||||
<bean id="instance" class="com.hazelcast.core.Hazelcast"
|
||||
factory-method="newHazelcastInstance">
|
||||
<constructor-arg>
|
||||
<bean class="com.hazelcast.config.Config" />
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
```
|
||||
**Reference :** http://docs.hazelcast.org/docs/latest/manual/html/distributedevents.html
|
||||
|
||||
|
||||
## HAZELCAST DISTRIBUTED-SQL INBOUND CHANNEL ADAPTER
|
||||
|
||||
Hazelcast allows to run distributed queries on the distributed map. Hazelcast Distributed SQL Inbound Channel Adapter is a poller-driven inbound channel adapter. It runs defined distributed-sql and returns results in the light of iteration type. Its basic definition is as follows :
|
||||
|
||||
@@ -12,7 +12,7 @@ buildscript {
|
||||
maven { url 'http://repo.spring.io/plugins-release' }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'org.springframework.build.gradle:spring-io-plugin:0.0.3.RELEASE'
|
||||
classpath 'io.spring.gradle:spring-io-plugin:0.0.4.RELEASE'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,12 @@ repositories {
|
||||
if (project.hasProperty('platformVersion')) {
|
||||
apply plugin: 'spring-io'
|
||||
|
||||
dependencies {
|
||||
springIoVersions "io.spring.platform:platform-bom:${platformVersion}@properties"
|
||||
dependencyManagement {
|
||||
springIoTestRuntime {
|
||||
imports {
|
||||
mavenBom "io.spring.platform:platform-bom:${platformVersion}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +71,8 @@ dependencies {
|
||||
compile "org.springframework.integration:spring-integration-core:$springIntegrationVersion"
|
||||
compile "com.hazelcast:hazelcast:$hazelcastVersion"
|
||||
|
||||
testCompile "com.hazelcast:hazelcast-client:$hazelcastVersion"
|
||||
|
||||
testCompile "org.springframework.integration:spring-integration-test:$springIntegrationVersion"
|
||||
|
||||
testRuntime "org.slf4j:slf4j-log4j12:$slf4jVersion"
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.hazelcast;
|
||||
|
||||
/**
|
||||
* Enumeration of Hazelcast Cluster Monitor Types
|
||||
*
|
||||
* @author Eren Avsarogullari
|
||||
* @since 1.0.0
|
||||
* @see org.springframework.integration.hazelcast.inbound.HazelcastClusterMonitorMessageProducer
|
||||
* @see com.hazelcast.core.MembershipListener
|
||||
* @see com.hazelcast.core.DistributedObjectListener
|
||||
* @see com.hazelcast.core.MigrationListener
|
||||
* @see com.hazelcast.core.LifecycleListener
|
||||
* @see com.hazelcast.core.ClientListener
|
||||
*/
|
||||
public enum ClusterMonitorType {
|
||||
|
||||
MEMBERSHIP, DISTRIBUTED_OBJECT, MIGRATION, LIFECYCLE, CLIENT;
|
||||
|
||||
}
|
||||
@@ -40,11 +40,13 @@ import com.hazelcast.core.ReplicatedMap;
|
||||
*/
|
||||
public class HazelcastIntegrationDefinitionValidator {
|
||||
|
||||
public static <E extends Enum<E>> void validateEnumType(final Class<E> enumType, final String cacheEventTypes) {
|
||||
Set<String> eventTypeSet = StringUtils.commaDelimitedListToSet(cacheEventTypes);
|
||||
for (String eventType : eventTypeSet) {
|
||||
Enum.valueOf(enumType, eventType);
|
||||
public static <E extends Enum<E>> Set<String> validateEnumType(final Class<E> enumType, final String types) {
|
||||
Set<String> typeSet = StringUtils.commaDelimitedListToSet(types);
|
||||
for (String type : typeSet) {
|
||||
Enum.valueOf(enumType, type);
|
||||
}
|
||||
|
||||
return typeSet;
|
||||
}
|
||||
|
||||
public static void validateCacheTypeForEventDrivenMessageProducer(final DistributedObject distributedObject) {
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.hazelcast.config.xml;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.hazelcast.inbound.HazelcastClusterMonitorMessageProducer;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parser for the {@code <int-hazelcast:cm-inbound-channel-adapter />} component.
|
||||
*
|
||||
* @author Eren Avsarogullari
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class HazelcastClusterMonitorInboundChannelAdapterParser extends
|
||||
AbstractSingleBeanDefinitionParser {
|
||||
|
||||
private static final String CHANNEL_ATTRIBUTE = "channel";
|
||||
|
||||
private static final String HAZELCAST_INSTANCE_ATTRIBUTE = "hazelcast-instance";
|
||||
|
||||
private static final String MONITOR_TYPES_ATTRIBUTE = "monitor-types";
|
||||
|
||||
private static final String OUTPUT_CHANNEL = "outputChannel";
|
||||
|
||||
private static final String MONITOR_EVENT_TYPES = "monitorEventTypes";
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return HazelcastClusterMonitorMessageProducer.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition,
|
||||
ParserContext parserContext) throws BeanDefinitionStoreException {
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
|
||||
if (!element.hasAttribute(CHANNEL_ATTRIBUTE)) {
|
||||
id = id + ".adapter";
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(id)) {
|
||||
id = BeanDefinitionReaderUtils.generateBeanName(definition,
|
||||
parserContext.getRegistry());
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext,
|
||||
BeanDefinitionBuilder builder) {
|
||||
String channelName = element.getAttribute(CHANNEL_ATTRIBUTE);
|
||||
if (!StringUtils.hasText(channelName)) {
|
||||
channelName = IntegrationNamespaceUtils.createDirectChannel(element,
|
||||
parserContext);
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(element.getAttribute(HAZELCAST_INSTANCE_ATTRIBUTE))) {
|
||||
parserContext.getReaderContext().error(
|
||||
"'" + HAZELCAST_INSTANCE_ATTRIBUTE + "' attribute is required.",
|
||||
element);
|
||||
}
|
||||
|
||||
builder.addPropertyReference(OUTPUT_CHANNEL, channelName);
|
||||
builder.addConstructorArgReference(element
|
||||
.getAttribute(HAZELCAST_INSTANCE_ATTRIBUTE));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
MONITOR_TYPES_ATTRIBUTE, MONITOR_EVENT_TYPES);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IntegrationNamespaceUtils.AUTO_STARTUP);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IntegrationNamespaceUtils.PHASE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,6 +32,7 @@ public class HazelcastIntegrationNamespaceHandler extends AbstractIntegrationNam
|
||||
registerBeanDefinitionParser("outbound-channel-adapter", new HazelcastOutboundChannelAdapterParser());
|
||||
registerBeanDefinitionParser("cq-inbound-channel-adapter", new HazelcastContinuousQueryInboundChannelAdapterParser());
|
||||
registerBeanDefinitionParser("ds-inbound-channel-adapter", new HazelcastDistributedSQLInboundChannelAdapterParser());
|
||||
registerBeanDefinitionParser("cm-inbound-channel-adapter", new HazelcastClusterMonitorInboundChannelAdapterParser());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.springframework.integration.hazelcast.HazelcastLocalInstanceRegistrar
|
||||
import org.springframework.integration.hazelcast.message.EntryEventMessagePayload;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.hazelcast.core.AbstractIMapEvent;
|
||||
import com.hazelcast.core.DistributedObject;
|
||||
@@ -71,11 +70,11 @@ public abstract class AbstractHazelcastMessageProducer extends MessageProducerSu
|
||||
}
|
||||
|
||||
public void setCacheEventTypes(String cacheEventTypes) {
|
||||
HazelcastIntegrationDefinitionValidator.validateEnumType(CacheEventType.class, cacheEventTypes);
|
||||
Set<String> cacheEvents = StringUtils.commaDelimitedListToSet(cacheEventTypes);
|
||||
Set<String> cacheEvents =
|
||||
HazelcastIntegrationDefinitionValidator.validateEnumType(CacheEventType.class, cacheEventTypes);
|
||||
Assert.notEmpty(cacheEvents, "'cacheEvents' must have elements");
|
||||
HazelcastIntegrationDefinitionValidator.validateCacheEventsByDistributedObject(
|
||||
this.distributedObject, cacheEvents);
|
||||
HazelcastIntegrationDefinitionValidator.validateCacheEventsByDistributedObject(this.distributedObject,
|
||||
cacheEvents);
|
||||
this.cacheEvents = cacheEvents;
|
||||
}
|
||||
|
||||
@@ -103,7 +102,7 @@ public abstract class AbstractHazelcastMessageProducer extends MessageProducerSu
|
||||
protected abstract Message<?> toMessage(E event);
|
||||
|
||||
protected void sendMessage(E event, InetSocketAddress socketAddress,
|
||||
CacheListeningPolicyType cacheListeningPolicyType) {
|
||||
CacheListeningPolicyType cacheListeningPolicyType) {
|
||||
if (CacheListeningPolicyType.ALL == cacheListeningPolicyType || isEventAcceptable(socketAddress)) {
|
||||
AbstractHazelcastMessageProducer.this.sendMessage(toMessage(event));
|
||||
}
|
||||
@@ -178,12 +177,11 @@ public abstract class AbstractHazelcastMessageProducer extends MessageProducerSu
|
||||
@Override
|
||||
protected void processEvent(AbstractIMapEvent event) {
|
||||
if (getCacheEvents().contains(event.getEventType().toString())) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Received Event : " + event);
|
||||
}
|
||||
sendMessage(event, event.getMember().getSocketAddress(), getCacheListeningPolicy());
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Received Event : " + event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.hazelcast.inbound;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.integration.endpoint.MessageProducerSupport;
|
||||
import org.springframework.integration.hazelcast.ClusterMonitorType;
|
||||
import org.springframework.integration.hazelcast.HazelcastIntegrationDefinitionValidator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.hazelcast.core.Client;
|
||||
import com.hazelcast.core.ClientListener;
|
||||
import com.hazelcast.core.DistributedObjectEvent;
|
||||
import com.hazelcast.core.DistributedObjectListener;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.hazelcast.core.LifecycleEvent;
|
||||
import com.hazelcast.core.LifecycleListener;
|
||||
import com.hazelcast.core.MemberAttributeEvent;
|
||||
import com.hazelcast.core.MembershipEvent;
|
||||
import com.hazelcast.core.MembershipListener;
|
||||
import com.hazelcast.core.MigrationEvent;
|
||||
import com.hazelcast.core.MigrationListener;
|
||||
|
||||
/**
|
||||
* Hazelcast Cluster Monitor Event Driven Message Producer is a message producer which
|
||||
* enables {@link HazelcastClusterMonitorMessageProducer.HazelcastClusterMonitorListener}
|
||||
* listener in order to listen cluster related events and sends events to related channel.
|
||||
*
|
||||
* @author Eren Avsarogullari
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class HazelcastClusterMonitorMessageProducer extends MessageProducerSupport {
|
||||
|
||||
private final HazelcastInstance hazelcastInstance;
|
||||
|
||||
private Set<String> monitorTypes = Collections.singleton(ClusterMonitorType.MEMBERSHIP.name());
|
||||
|
||||
private final Map<ClusterMonitorType, String> hazelcastRegisteredListenerIdMap = new ConcurrentHashMap<>(5);
|
||||
|
||||
public HazelcastClusterMonitorMessageProducer(HazelcastInstance hazelcastInstance) {
|
||||
Assert.notNull(hazelcastInstance, "'hazelcastInstance' must not be null");
|
||||
this.hazelcastInstance = hazelcastInstance;
|
||||
}
|
||||
|
||||
public void setMonitorEventTypes(String monitorEventTypes) {
|
||||
final Set<String> monitorTypes =
|
||||
HazelcastIntegrationDefinitionValidator.validateEnumType(ClusterMonitorType.class, monitorEventTypes);
|
||||
Assert.notEmpty(monitorTypes, "'monitorTypes' must have elements");
|
||||
this.monitorTypes = monitorTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() {
|
||||
final HazelcastClusterMonitorListener clusterMonitorListener = new HazelcastClusterMonitorListener();
|
||||
|
||||
if (this.monitorTypes.contains(ClusterMonitorType.MEMBERSHIP.name())) {
|
||||
final String registrationId = this.hazelcastInstance.getCluster()
|
||||
.addMembershipListener(clusterMonitorListener);
|
||||
this.hazelcastRegisteredListenerIdMap.put(ClusterMonitorType.MEMBERSHIP, registrationId);
|
||||
}
|
||||
|
||||
if (this.monitorTypes.contains(ClusterMonitorType.DISTRIBUTED_OBJECT.name())) {
|
||||
final String registrationId = this.hazelcastInstance
|
||||
.addDistributedObjectListener(clusterMonitorListener);
|
||||
this.hazelcastRegisteredListenerIdMap.put(ClusterMonitorType.DISTRIBUTED_OBJECT, registrationId);
|
||||
}
|
||||
|
||||
if (this.monitorTypes.contains(ClusterMonitorType.MIGRATION.name())) {
|
||||
final String registrationId = this.hazelcastInstance.getPartitionService()
|
||||
.addMigrationListener(clusterMonitorListener);
|
||||
this.hazelcastRegisteredListenerIdMap.put(ClusterMonitorType.MIGRATION, registrationId);
|
||||
}
|
||||
|
||||
if (this.monitorTypes.contains(ClusterMonitorType.LIFECYCLE.name())) {
|
||||
final String registrationId = this.hazelcastInstance.getLifecycleService()
|
||||
.addLifecycleListener(clusterMonitorListener);
|
||||
this.hazelcastRegisteredListenerIdMap.put(ClusterMonitorType.LIFECYCLE, registrationId);
|
||||
}
|
||||
|
||||
if (this.monitorTypes.contains(ClusterMonitorType.CLIENT.name())) {
|
||||
final String registrationId = this.hazelcastInstance.getClientService()
|
||||
.addClientListener(clusterMonitorListener);
|
||||
this.hazelcastRegisteredListenerIdMap.put(ClusterMonitorType.CLIENT, registrationId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() {
|
||||
if (this.hazelcastInstance.getLifecycleService().isRunning()) {
|
||||
String id = this.hazelcastRegisteredListenerIdMap.remove(ClusterMonitorType.MEMBERSHIP);
|
||||
if (id != null) {
|
||||
this.hazelcastInstance.getCluster().removeMembershipListener(id);
|
||||
}
|
||||
|
||||
id = this.hazelcastRegisteredListenerIdMap.remove(ClusterMonitorType.DISTRIBUTED_OBJECT);
|
||||
if (id != null) {
|
||||
this.hazelcastInstance.removeDistributedObjectListener(id);
|
||||
}
|
||||
|
||||
id = this.hazelcastRegisteredListenerIdMap.remove(ClusterMonitorType.MIGRATION);
|
||||
if (id != null) {
|
||||
this.hazelcastInstance.getPartitionService().removeMigrationListener(id);
|
||||
}
|
||||
|
||||
id = this.hazelcastRegisteredListenerIdMap.remove(ClusterMonitorType.LIFECYCLE);
|
||||
if (id != null) {
|
||||
this.hazelcastInstance.getLifecycleService().removeLifecycleListener(id);
|
||||
}
|
||||
|
||||
id = this.hazelcastRegisteredListenerIdMap.remove(ClusterMonitorType.CLIENT);
|
||||
if (id != null) {
|
||||
this.hazelcastInstance.getClientService().removeClientListener(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
return "hazelcast:cm-inbound-channel-adapter";
|
||||
}
|
||||
|
||||
private void processEvent(Object event) {
|
||||
Assert.notNull(event, "'hazelcast event' must not be null");
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Received Cluster Monitor Event : " + event);
|
||||
}
|
||||
this.sendMessage(getMessageBuilderFactory().withPayload(event).build());
|
||||
|
||||
}
|
||||
|
||||
private final class HazelcastClusterMonitorListener implements MembershipListener,
|
||||
DistributedObjectListener, MigrationListener, LifecycleListener,
|
||||
ClientListener {
|
||||
|
||||
@Override
|
||||
public void memberAdded(MembershipEvent membershipEvent) {
|
||||
processEvent(membershipEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void memberRemoved(MembershipEvent membershipEvent) {
|
||||
processEvent(membershipEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void memberAttributeChanged(MemberAttributeEvent memberAttributeEvent) {
|
||||
processEvent(memberAttributeEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void distributedObjectCreated(DistributedObjectEvent event) {
|
||||
processEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void distributedObjectDestroyed(DistributedObjectEvent event) {
|
||||
processEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrationStarted(MigrationEvent migrationEvent) {
|
||||
processEvent(migrationEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrationCompleted(MigrationEvent migrationEvent) {
|
||||
processEvent(migrationEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void migrationFailed(MigrationEvent migrationEvent) {
|
||||
processEvent(migrationEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(LifecycleEvent event) {
|
||||
processEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clientConnected(Client client) {
|
||||
processEvent(client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clientDisconnected(Client client) {
|
||||
processEvent(client);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import java.util.Map;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.expression.ExpressionUtils;
|
||||
import org.springframework.integration.expression.IntegrationEvaluationContextAware;
|
||||
import org.springframework.integration.handler.AbstractMessageHandler;
|
||||
import org.springframework.integration.hazelcast.HazelcastHeaders;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
@@ -257,4 +257,47 @@
|
||||
</xsd:complexType>
|
||||
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="cm-inbound-channel-adapter">
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Configures Hazelcast Cluster Monitor Inbound Channel Adapter
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:complexType>
|
||||
|
||||
<xsd:attributeGroup ref="integration:channelAdapterAttributes"/>
|
||||
|
||||
<xsd:attribute name="hazelcast-instance" use="required" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="com.hazelcast.core.HazelcastInstance" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
<![CDATA[ Specifies hazelcast instance reference to listen ]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
|
||||
<xsd:attribute name="monitor-types" type="xsd:string" use="optional" default="MEMBERSHIP">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="value">
|
||||
<tool:expected-type
|
||||
type="org.springframework.integration.hazelcast.ClusterMonitorType" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
<![CDATA[ Specifies cluster monitor types ]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
</xsd:element>
|
||||
|
||||
</xsd:schema>
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-hazelcast="http://www.springframework.org/schema/integration/hazelcast"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/hazelcast
|
||||
http://www.springframework.org/schema/integration/hazelcast/spring-integration-hazelcast.xsd">
|
||||
|
||||
<int:channel id="cmChannel1">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
<int:channel id="cmChannel2">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
<int:channel id="cmChannel3">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
<int:channel id="cmChannel4">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
<int:channel id="cmChannel5">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
<int:channel id="cmChannel6">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
<int-hazelcast:cm-inbound-channel-adapter
|
||||
channel="cmChannel1"
|
||||
hazelcast-instance="hazelcastInstance"
|
||||
monitor-types="MEMBERSHIP" />
|
||||
|
||||
<int-hazelcast:cm-inbound-channel-adapter
|
||||
channel="cmChannel2"
|
||||
hazelcast-instance="hazelcastInstance"
|
||||
monitor-types="DISTRIBUTED_OBJECT" />
|
||||
|
||||
<int-hazelcast:cm-inbound-channel-adapter
|
||||
channel="cmChannel3"
|
||||
hazelcast-instance="hazelcastInstance"
|
||||
monitor-types="MIGRATION" />
|
||||
|
||||
<int-hazelcast:cm-inbound-channel-adapter
|
||||
channel="cmChannel4"
|
||||
hazelcast-instance="hazelcastInstance2"
|
||||
monitor-types="LIFECYCLE" />
|
||||
|
||||
<int-hazelcast:cm-inbound-channel-adapter
|
||||
channel="cmChannel5"
|
||||
hazelcast-instance="hazelcastInstance"
|
||||
monitor-types="CLIENT" />
|
||||
|
||||
<int-hazelcast:cm-inbound-channel-adapter
|
||||
channel="cmChannel6"
|
||||
hazelcast-instance="hazelcastInstance"
|
||||
monitor-types="MEMBERSHIP,DISTRIBUTED_OBJECT" />
|
||||
|
||||
<bean id="hazelcastInstance" class="com.hazelcast.core.Hazelcast" factory-method="newHazelcastInstance"
|
||||
destroy-method="shutdown">
|
||||
<constructor-arg>
|
||||
<bean class="com.hazelcast.config.Config">
|
||||
<property name="groupConfig">
|
||||
<bean class="com.hazelcast.config.GroupConfig">
|
||||
<property name="name" value="Test_Group_Name1"/>
|
||||
<property name="password" value="dev-pass"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="networkConfig">
|
||||
<bean class="com.hazelcast.config.NetworkConfig">
|
||||
<property name="port" value="5701"/>
|
||||
<property name="portAutoIncrement" value="false"/>
|
||||
<property name="join">
|
||||
<bean class="com.hazelcast.config.JoinConfig">
|
||||
<property name="multicastConfig">
|
||||
<bean class="com.hazelcast.config.MulticastConfig">
|
||||
<property name="enabled" value="false" />
|
||||
</bean>
|
||||
</property>
|
||||
<property name="tcpIpConfig">
|
||||
<bean class="com.hazelcast.config.TcpIpConfig">
|
||||
<property name="members" value="127.0.0.1:5701,127.0.0.1:5703" />
|
||||
<property name="enabled" value="true" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="hazelcastInstance2" class="com.hazelcast.core.Hazelcast" factory-method="newHazelcastInstance"
|
||||
destroy-method="shutdown">
|
||||
<constructor-arg>
|
||||
<bean class="com.hazelcast.config.Config">
|
||||
<property name="groupConfig">
|
||||
<bean class="com.hazelcast.config.GroupConfig">
|
||||
<property name="name" value="Test_Group_Name2"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="networkConfig">
|
||||
<bean class="com.hazelcast.config.NetworkConfig">
|
||||
<property name="port" value="5702"/>
|
||||
<property name="portAutoIncrement" value="false"/>
|
||||
<property name="join">
|
||||
<bean class="com.hazelcast.config.JoinConfig">
|
||||
<property name="multicastConfig">
|
||||
<bean class="com.hazelcast.config.MulticastConfig">
|
||||
<property name="enabled" value="false" />
|
||||
</bean>
|
||||
</property>
|
||||
<property name="tcpIpConfig">
|
||||
<bean class="com.hazelcast.config.TcpIpConfig">
|
||||
<property name="members" value="127.0.0.1:5702" />
|
||||
<property name="enabled" value="true" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="hazelcastInstance3" class="com.hazelcast.core.Hazelcast" factory-method="newHazelcastInstance"
|
||||
destroy-method="shutdown">
|
||||
<constructor-arg>
|
||||
<bean class="com.hazelcast.config.Config">
|
||||
<property name="groupConfig">
|
||||
<bean class="com.hazelcast.config.GroupConfig">
|
||||
<property name="name" value="Test_Group_Name1"/>
|
||||
<property name="password" value="dev-pass"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="networkConfig">
|
||||
<bean class="com.hazelcast.config.NetworkConfig">
|
||||
<property name="port" value="5703"/>
|
||||
<property name="portAutoIncrement" value="false"/>
|
||||
<property name="join">
|
||||
<bean class="com.hazelcast.config.JoinConfig">
|
||||
<property name="multicastConfig">
|
||||
<bean class="com.hazelcast.config.MulticastConfig">
|
||||
<property name="enabled" value="false" />
|
||||
</bean>
|
||||
</property>
|
||||
<property name="tcpIpConfig">
|
||||
<bean class="com.hazelcast.config.TcpIpConfig">
|
||||
<property name="members" value="127.0.0.1:5701,127.0.0.1:5703" />
|
||||
<property name="enabled" value="true" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.hazelcast.inbound;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.hazelcast.client.HazelcastClient;
|
||||
import com.hazelcast.client.config.ClientConfig;
|
||||
import com.hazelcast.config.GroupConfig;
|
||||
import com.hazelcast.core.Client;
|
||||
import com.hazelcast.core.ClientType;
|
||||
import com.hazelcast.core.DistributedObjectEvent;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.hazelcast.core.IMap;
|
||||
import com.hazelcast.core.LifecycleEvent;
|
||||
import com.hazelcast.core.Member;
|
||||
import com.hazelcast.core.LifecycleEvent.LifecycleState;
|
||||
import com.hazelcast.core.MembershipEvent;
|
||||
import com.hazelcast.core.MigrationEvent;
|
||||
|
||||
/**
|
||||
* Hazelcast Cluster Monitor Inbound Channel Adapter Unit Test Class
|
||||
*
|
||||
* @author Eren Avsarogullari
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@DirtiesContext
|
||||
public class HazelcastClusterMonitorInboundChannelAdapterTests {
|
||||
|
||||
private static final String TEST_GROUP_NAME1 = "Test_Group_Name1";
|
||||
|
||||
private static final int TIMEOUT = 10_000;
|
||||
|
||||
@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;
|
||||
|
||||
@Test
|
||||
public void testMembershipEvent() {
|
||||
testMembershipEvent(hazelcastInstance, cmChannel1, "testKey1", "testValue1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistributedObjectEvent() {
|
||||
testDistributedObjectEventByChannelAndHazelcastInstance(cmChannel2,
|
||||
hazelcastInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMigrationEvent() {
|
||||
final IMap<Integer, String> distributedMap = hazelcastInstance3
|
||||
.getMap("Test_Distributed_Map2");
|
||||
distributedMap.put(1, "TestValue1");
|
||||
distributedMap.put(2, "TestValue2");
|
||||
|
||||
hazelcastInstance3.getLifecycleService().terminate();
|
||||
final Message<?> msg = cmChannel3.receive(TIMEOUT);
|
||||
verifyMigrationEvent(msg);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycleEvent() throws InterruptedException {
|
||||
hazelcastInstance2.getLifecycleService().terminate();
|
||||
|
||||
Message<?> msg = cmChannel4.receive(TIMEOUT);
|
||||
verifyLifecycleEvent(msg, LifecycleState.SHUTTING_DOWN);
|
||||
|
||||
msg = cmChannel4.receive(TIMEOUT);
|
||||
verifyLifecycleEvent(msg, LifecycleState.SHUTDOWN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientEvent() {
|
||||
testClientEventByChannelAndGroupName(cmChannel5, TEST_GROUP_NAME1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleMonitorTypes() {
|
||||
testDistributedObjectEventByChannelAndHazelcastInstance(cmChannel6,
|
||||
hazelcastInstance);
|
||||
|
||||
testMembershipEvent(hazelcastInstance, cmChannel6, "testKey2", "testValue2");
|
||||
}
|
||||
|
||||
private void testMembershipEvent(
|
||||
final HazelcastInstance instance, final PollableChannel channel,
|
||||
final String key, final String value) {
|
||||
Member member = instance.getCluster().getMembers().iterator().next();
|
||||
member.setStringAttribute(key, value);
|
||||
|
||||
Message<?> msg = channel.receive(TIMEOUT);
|
||||
verifyMembershipEvent(msg, MembershipEvent.MEMBER_ATTRIBUTE_CHANGED);
|
||||
}
|
||||
|
||||
private void testClientEventByChannelAndGroupName(final PollableChannel channel,
|
||||
final String groupName) {
|
||||
final HazelcastInstance client = getHazelcastClientByGroupName(groupName);
|
||||
|
||||
Message<?> msg = channel.receive(TIMEOUT);
|
||||
verifyClientEvent(msg);
|
||||
|
||||
client.getLifecycleService().terminate();
|
||||
|
||||
msg = channel.receive(TIMEOUT);
|
||||
verifyClientEvent(msg);
|
||||
}
|
||||
|
||||
private void testDistributedObjectEventByChannelAndHazelcastInstance(
|
||||
final PollableChannel channel, final HazelcastInstance hazelcastInstance) {
|
||||
final String distributedObjectName = "Test_Distributed_Map";
|
||||
final IMap<Integer, String> distributedMap = hazelcastInstance
|
||||
.getMap(distributedObjectName);
|
||||
|
||||
Message<?> msg = channel.receive(TIMEOUT);
|
||||
verifyDistributedObjectEvent(msg, DistributedObjectEvent.EventType.CREATED,
|
||||
distributedObjectName);
|
||||
|
||||
distributedMap.destroy();
|
||||
|
||||
msg = channel.receive(TIMEOUT);
|
||||
verifyDistributedObjectEvent(msg, DistributedObjectEvent.EventType.DESTROYED,
|
||||
distributedObjectName);
|
||||
}
|
||||
|
||||
private HazelcastInstance getHazelcastClientByGroupName(final String groupName) {
|
||||
final GroupConfig groupConfig = new GroupConfig();
|
||||
groupConfig.setName(groupName);
|
||||
groupConfig.setPassword("dev-pass");
|
||||
final ClientConfig cfg = new ClientConfig();
|
||||
cfg.setGroupConfig(groupConfig);
|
||||
cfg.getNetworkConfig().addAddress("127.0.0.1:5701");
|
||||
|
||||
return HazelcastClient.newHazelcastClient(cfg);
|
||||
}
|
||||
|
||||
private void verifyMembershipEvent(final Message<?> msg, final int membershipEvent) {
|
||||
assertNotNull(msg);
|
||||
assertNotNull(msg.getPayload());
|
||||
assertTrue(msg.getPayload() instanceof MembershipEvent);
|
||||
assertEquals(membershipEvent, ((MembershipEvent) msg.getPayload()).getEventType());
|
||||
assertNotNull(((MembershipEvent) msg.getPayload()).getMember());
|
||||
}
|
||||
|
||||
private void verifyDistributedObjectEvent(final Message<?> msg,
|
||||
final DistributedObjectEvent.EventType eventType,
|
||||
final String distributedObjectName) {
|
||||
assertNotNull(msg);
|
||||
assertNotNull(msg.getPayload());
|
||||
assertTrue(msg.getPayload() instanceof DistributedObjectEvent);
|
||||
assertEquals(eventType, ((DistributedObjectEvent) msg.getPayload()).getEventType());
|
||||
assertNotNull(
|
||||
(((DistributedObjectEvent) msg.getPayload()).getDistributedObject())
|
||||
.getName(),
|
||||
distributedObjectName);
|
||||
}
|
||||
|
||||
private void verifyMigrationEvent(final Message<?> msg) {
|
||||
assertNotNull(msg);
|
||||
assertNotNull(msg.getPayload());
|
||||
assertTrue(msg.getPayload() instanceof MigrationEvent);
|
||||
assertNotNull(((MigrationEvent) msg.getPayload()).getStatus());
|
||||
assertNotNull(((MigrationEvent) msg.getPayload()).getNewOwner());
|
||||
assertNotNull(((MigrationEvent) msg.getPayload()).getOldOwner());
|
||||
}
|
||||
|
||||
private void verifyLifecycleEvent(final Message<?> msg,
|
||||
final LifecycleState lifecycleState) {
|
||||
assertNotNull(msg);
|
||||
assertNotNull(msg.getPayload());
|
||||
assertTrue(msg.getPayload() instanceof LifecycleEvent);
|
||||
assertEquals(lifecycleState, ((LifecycleEvent) msg.getPayload()).getState());
|
||||
}
|
||||
|
||||
private void verifyClientEvent(final Message<?> msg) {
|
||||
assertNotNull(msg);
|
||||
assertNotNull(msg.getPayload());
|
||||
assertTrue(msg.getPayload() instanceof Client);
|
||||
assertEquals(ClientType.JAVA, ((Client) msg.getPayload()).getClientType());
|
||||
assertNotNull(((Client) msg.getPayload()).getSocketAddress());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user