/* * Copyright 2002-2017 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.gemfire.inbound; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.geode.cache.query.CqEvent; import org.springframework.data.gemfire.listener.ContinuousQueryDefinition; import org.springframework.data.gemfire.listener.ContinuousQueryListener; import org.springframework.data.gemfire.listener.ContinuousQueryListenerContainer; import org.springframework.integration.endpoint.ExpressionMessageProducerSupport; import org.springframework.messaging.Message; import org.springframework.util.Assert; /** * Responds to a Gemfire continuous query (set using the #query field) that is * constantly evaluated against a cache * {@link org.apache.geode.cache.Region}. This is much faster than * re-querying the cache manually. * * @author Josh Long * @author David Turanski * @author Artem Bilan * @since 2.1 * */ public class ContinuousQueryMessageProducer extends ExpressionMessageProducerSupport implements ContinuousQueryListener { private static Log logger = LogFactory.getLog(ContinuousQueryMessageProducer.class); private final String query; private final ContinuousQueryListenerContainer queryListenerContainer; private volatile String queryName; private boolean durable; private volatile Set<CqEventType> supportedEventTypes = new HashSet<CqEventType>(Arrays.asList(CqEventType.CREATED, CqEventType.UPDATED)); /** * @param queryListenerContainer a {@link ContinuousQueryListenerContainer} * @param query the query string */ public ContinuousQueryMessageProducer(ContinuousQueryListenerContainer queryListenerContainer, String query) { Assert.notNull(queryListenerContainer, "'queryListenerContainer' cannot be null"); Assert.notNull(query, "'query' cannot be null"); this.queryListenerContainer = queryListenerContainer; this.query = query; } /** * @param queryName optional query name */ public void setQueryName(String queryName) { this.queryName = queryName; } /** * @param durable true if the query is a durable subscription */ public void setDurable(boolean durable) { this.durable = durable; } public void setSupportedEventTypes(CqEventType... eventTypes) { Assert.notEmpty(eventTypes, "eventTypes must not be empty"); this.supportedEventTypes = new HashSet<CqEventType>(Arrays.asList(eventTypes)); } @Override public String getComponentType() { return "gemfire:cq-inbound-channel-adapter"; } @Override protected void onInit() { super.onInit(); if (this.queryName == null) { this.queryListenerContainer.addListener(new ContinuousQueryDefinition(this.query, this, this.durable)); } else { this.queryListenerContainer.addListener(new ContinuousQueryDefinition(this.queryName, this.query, this, this.durable)); } } /* * (non-Javadoc) * @see org.springframework.data.gemfire.listener.QueryListener#onEvent(com.gemstone.gemfire.cache.query.CqEvent) */ @Override public void onEvent(CqEvent event) { if (isEventSupported(event)) { if (logger.isDebugEnabled()) { logger.debug(String.format("processing cq event key [%s] event [%s]", event.getQueryOperation() .toString(), event.getKey())); } Message<?> message = null; Object object = evaluatePayloadExpression(event); if (object instanceof Message) { message = (Message<?>) object; } else { message = getMessageBuilderFactory().withPayload(object).build(); } sendMessage(message); } } private boolean isEventSupported(CqEvent event) { String eventName = event.getQueryOperation().toString() + (event.getQueryOperation().toString().endsWith("Y") ? "ED" : "D"); CqEventType eventType = CqEventType.valueOf(eventName); return this.supportedEventTypes.contains(eventType); } }