INT-2074 - refactored ContinuousQueryMessageProducer and cleaned up tests

This commit is contained in:
David Turanski
2011-08-22 17:18:53 -04:00
parent 449dfc9fac
commit ee8c4e2d69
14 changed files with 311 additions and 458 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<beansProjectDescription>
<version>1</version>
<pluginVersion><![CDATA[2.7.1.201107082359-RELEASE]]></pluginVersion>
<pluginVersion><![CDATA[2.8.0.201108100015-M1]]></pluginVersion>
<configSuffixes>
<configSuffix><![CDATA[xml]]></configSuffix>
</configSuffixes>
@@ -9,6 +9,7 @@
<configs>
<config>src/test/java/org/springframework/integration/gemfire/inbound/GemfireInboundChannelAdapterTests-context.xml</config>
<config>src/test/java/org/springframework/integration/gemfire/outbound/GemfireOutboundChannelAdapterTests-context.xml</config>
<config>src/test/java/org/springframework/integration/gemfire/inbound/cq/ContinuousQueryMessageProducerTests-context.xml</config>
</configs>
<configSets>
</configSets>

View File

@@ -16,182 +16,87 @@
package org.springframework.integration.gemfire.inbound;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.query.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.gemfire.listener.CqQueryDefinition;
import org.springframework.data.gemfire.listener.QueryListener;
import org.springframework.data.gemfire.listener.QueryListenerContainer;
import org.springframework.integration.Message;
import org.springframework.integration.endpoint.MessageProducerSupport;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.gemstone.gemfire.cache.query.CqEvent;
/**
* Responds to a continuous query (set using the #queryString field) that is
* constantly evaluated against a cache {@link com.gemstone.gemfire.cache.Region}.
* This is much faster than re-querying the cache manually.
*
* Responds to a Gemfire continuous query (set using the #query field) that is
* constantly evaluated against a cache
* {@link com.gemstone.gemfire.cache.Region}. This is much faster than
* re-querying the cache manually.
*
* @author Josh Long
* @author David Turanski
* @since 2.1
*
*/
public class ContinuousQueryMessageProducer extends MessageProducerSupport {
private final Log logger = LogFactory.getLog(this.getClass());
public class ContinuousQueryMessageProducer extends MessageProducerSupport implements QueryListener {
private static Log logger = LogFactory.getLog(ContinuousQueryMessageProducer.class);
private final String query;
private final QueryListenerContainer queryListenerContainer;
private volatile String name;
private boolean durable;
/**
* Not sure yet if there's a way to avoid depending on this.
*
* @param queryListenerContainer a {@link org.springframework.data.gemfire.listener.QueryListenerContainer}
* @param query the query string
*/
private volatile Pool pool;
/**
* Must be provided by the client of this class
*/
private final Region<?, ?> region;
/**
* Is the queryString durable (optional)
*/
private volatile boolean durable = false;
/**
* the {@link com.gemstone.gemfire.cache.query.CqQuery} instance created and
* registered with the server
*/
private volatile CqQuery cqQuery;
/**
* the query to be registered against the cache
*/
private final String queryString;
/**
* a reference to a {@link com.gemstone.gemfire.cache.query.QueryService}
* that is obtained through the #regionService instance.
*/
private volatile QueryService queryService;
/**
* used when building the queryString itself - optional
*/
private volatile String queryName;
/**
* a {@link com.gemstone.gemfire.cache.query.CqAttributesFactory} to generate
* the {@link com.gemstone.gemfire.cache.query.CqAttributes} that in turn
* hold the reference to the listener that we register to in turn funnel
* messages to the clients of this adapter.
*/
private final CqAttributesFactory cqAttributesFactory = new CqAttributesFactory();
/**
* the adapter requires a query string to continuously evaluate as well as a
* {@link com.gemstone.gemfire.cache.Region} against which to evaluate the
* query.
*
* @param region
* the region against which the query should be evaluated
* @param queryString
* the query string
*/
public ContinuousQueryMessageProducer(Region<?, ?> region, Pool pool, String queryString) {
this.region = region;
Assert.notNull(this.region, "You must provide a reference to a 'Region'");
this.pool = pool;
Assert.notNull(this.pool, "You must provide a 'pool'");
this.queryString = queryString;
Assert.hasText(this.queryString, "You must provide a queryString to evaluate against the region");
public ContinuousQueryMessageProducer(QueryListenerContainer queryListenerContainer, String query) {
Assert.notNull(queryListenerContainer, "'queryListenerContainer' cannot be null");
Assert.notNull(query, "'query' cannot be null");
this.queryListenerContainer = queryListenerContainer;
this.query = query;
}
/**
* whether or not the query is durable (that is, whether or not this query
* should live beyond the registered query)
*
* @param durable
* whether or not the query is registered and saved and
* subsequently retrievable by a query name.
*
* @param name optional query name
*/
public void setName(String name) {
this.name = name;
}
/**
*
* @param durable true if the query is a durable subscription
*/
public void setDurable(boolean durable) {
this.durable = durable;
}
/**
* Specify the name of the queryString (optional).
*/
public void setQueryName(String queryName) {
this.queryName = queryName;
}
@Override
protected void doStart() {
try {
cqQuery.execute();
}
catch (Throwable e) {
throw new RuntimeException("Failed to start the continuous query", e);
}
}
@Override
protected void doStop() {
try {
this.cqQuery.stop();
}
catch (CqException e) {
throw new RuntimeException("Failed to stop the continuous query", e);
}
}
/**
* hook to handle registration of the query
*/
private CqQuery registerContinuousQuery(QueryService queryService,
String name, String query, boolean durable, CqListener cqListener) throws Throwable {
cqAttributesFactory.addCqListener(cqListener);
CqAttributes attrs = cqAttributesFactory.create();
CqQuery cqQuery = queryService.newCq(name, query, attrs, durable);
return cqQuery;
}
@Override
protected void onInit() {
try {
super.onInit();
// regionService = this.region.getRegionService();
queryService = this.pool.getQueryService();
String defaultName = String.format("%s-%s-query",
getComponentName() + "", getComponentType() + "");
queryName = StringUtils.hasText(queryName) ? queryName : defaultName;
this.cqQuery = registerContinuousQuery(queryService, queryName,
this.queryString, this.durable,
new MessageProducingCqListener());
}
catch (Throwable e) {
throw new RuntimeException("Couldn't properly setup the " + getClass().getName(), e);
super.onInit();
if (name == null){
queryListenerContainer.addListener(new CqQueryDefinition(this.query, this, this.durable));
} else {
queryListenerContainer.addListener(new CqQueryDefinition(this.name, this.query, this, this.durable));
}
}
/**
* Listener that listens for any events being broadcast as a result of the
* evaluation of a continuous query {@link CqQuery}.
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.gemfire.listener.QueryListener#onEvent(com.gemstone
* .gemfire.cache.query.CqEvent)
*/
class MessageProducingCqListener implements CqListener {
public void onEvent(CqEvent cqEvent) {
Message<CqEvent> cqEventMessage = MessageBuilder.withPayload(cqEvent).build();
sendMessage(cqEventMessage);
}
public void onError(CqEvent cqEvent) {
logger.debug("error on " + getClass() + " (a CqListener) ");
throw new RuntimeException("error when interacting with region.", cqEvent.getThrowable());
}
public void close() {
logger.debug(getClass() + " close() called");
public void onEvent(CqEvent event) {
if (logger.isDebugEnabled()){
logger.debug(String.format("processing cq event key [%s] event [%s]",event.getBaseOperation().toString(),event.getKey()));
}
Message<CqEvent> cqEventMessage = MessageBuilder.withPayload(event).build();
sendMessage(cqEventMessage);
}
}

View File

@@ -31,14 +31,18 @@ import com.gemstone.gemfire.distributed.DistributedSystem;
/**
* @author Costin Leau
* @author David Turanski
*
* Runs as a standalone Java app.
* Modified from SGF implementation for testing client/server CQ features
*/
public class CacheServerProcess {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
props.setProperty("name", "CqServer");
props.setProperty("log-level", "warning");
props.setProperty("name", "CacheServer");
props.setProperty("log-level", "info");
System.out.println("\nConnecting to the distributed system and creating the cache.");
DistributedSystem ds = DistributedSystem.connect(props);
@@ -48,28 +52,20 @@ public class CacheServerProcess {
AttributesFactory factory = new AttributesFactory();
factory.setDataPolicy(DataPolicy.REPLICATE);
factory.setScope(Scope.DISTRIBUTED_ACK);
Region testRegion = cache.createRegion("test-cq", factory.create());
Region testRegion = cache.createRegion("test", factory.create());
System.out.println("Test region, " + testRegion.getFullPath() + ", created in cache.");
// Start Cache Server.
CacheServer server = cache.addCacheServer();
server.setPort(40404);
server.setNotifyBySubscription(true);
System.out.println("Starting server");
server.start();
System.out.println("Waiting for signal");
// wait for signal
System.out.println("Waiting for shutdown");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
bufferedReader.readLine();
System.out.println("Received signal");
testRegion.put("one", 1);
testRegion.put("two", 2);
testRegion.put("three", 3);
System.out.println("Waiting for shutdown");
bufferedReader.readLine();
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright 2011 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.fork;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Utility for forking Java processes. Modified from the SGF version for SI
*
* @author Costin Leau
* @author David Turanski
*
*
*/
public class ForkUtil {
public static OutputStream cloneJVM(String argument) {
String cp = System.getProperty("java.class.path");
String home = System.getProperty("java.home");
Process proc = null;
String java = home + "/bin/java ".replace("\\","/");;
String argCp = "-cp " + cp;
String argClass = argument;
String cmd = java + argCp + " " + argClass;
try {
//ProcessBuilder builder = new ProcessBuilder(cmd, argCp, argClass);
//builder.redirectErrorStream(true);
proc = Runtime.getRuntime().exec(cmd);
} catch (IOException ioe) {
throw new IllegalStateException("Cannot start command " + cmd, ioe);
}
System.out.println("Started fork");
final Process p = proc;
final BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
final AtomicBoolean run = new AtomicBoolean(true);
Thread reader = new Thread(new Runnable() {
public void run() {
try {
String line = null;
do {
while ((line = br.readLine()) != null) {
System.out.println("[FORK] " + line);
}
Thread.sleep(200);
} while (run.get());
} catch (Exception ex) {
// ignore and exit
}
}
});
reader.start();
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Stopping fork...");
run.set(false);
if (p != null)
p.destroy();
try {
p.waitFor();
} catch (InterruptedException e) {
// ignore
}
System.out.println("Fork stopped");
}
});
return proc.getOutputStream();
}
public static OutputStream cacheServer() {
OutputStream os = cloneJVM("org.springframework.integration.gemfire.fork.CacheServerProcess");
try {
Thread.sleep(8000);
} catch (InterruptedException ex) {
// ignore and move on
}
return os;
}
}

View File

@@ -0,0 +1,36 @@
<?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:gfe="http://www.springframework.org/schema/gemfire"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-gfe="http://www.springframework.org/schema/integration/gemfire"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/integration/gemfire http://www.springframework.org/schema/integration/scripting/spring-integration-gemfire.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire-1.1.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
<gfe:cache/>
<gfe:pool id="client-pool" subscription-enabled="true" >
<gfe:server host="localhost" port="40404"/>
</gfe:pool>
<gfe:client-region id="test" pool-name="client-pool" data-policy="EMPTY"/>
<bean id="queryListenerContainer" class="org.springframework.data.gemfire.listener.QueryListenerContainer">
<property name="cache" ref="gemfire-cache"/>
</bean>
<bean class="org.springframework.integration.gemfire.inbound.ContinuousQueryMessageProducer">
<constructor-arg ref="queryListenerContainer"/>
<constructor-arg value="select * from /test"/>
<property name="outputChannel" ref="outputChannel"/>
<property name="durable" value="true"/>
</bean>
<int:channel id="outputChannel">
<int:queue/>
</int:channel>
</beans>

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2002-2011 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.cq;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.OutputStream;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.gemfire.fork.ForkUtil;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.gemstone.gemfire.cache.query.CqEvent;
import com.gemstone.gemfire.internal.cache.LocalRegion;
/**
* @author David Turanski
* @since 2.1
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class ContinuousQueryMessageProducerTests {
@Autowired
LocalRegion region;
@Autowired
ConfigurableApplicationContext applicationContext;
@Autowired
PollableChannel outputChannel;
static OutputStream os;
@BeforeClass
public static void startUp() throws Exception {
os = ForkUtil.cacheServer();
}
@Test
public void test() throws InterruptedException {
region.put("one",1);
Message<?> msg = outputChannel.receive(1000);
assertNotNull(msg);
assertTrue(msg.getPayload() instanceof CqEvent);
/*
* Avoid shutdown errors
*/
applicationContext.close();
}
@AfterClass
public static void cleanUp() {
try {
Thread.sleep(3000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sendSignal();
}
public static void sendSignal() {
try {
os.write("\n".getBytes());
os.flush();
} catch (IOException ex) {
throw new IllegalStateException("Cannot communicate with forked VM", ex);
}
}
}

View File

@@ -1,15 +0,0 @@
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<int:channel id="cqIn"/>
<int:service-activator input-channel="cqIn" ref="cqServiceActivator"/>
</beans>

View File

@@ -1,25 +0,0 @@
<?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:util="http://www.springframework.org/schema/util"
xmlns:gfe="http://www.springframework.org/schema/gemfire" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="org/springframework/integration/gemfire/inbound/cq/common.properties"/>
<!-- setup the cache-->
<util:properties id="props" location="org/springframework/integration/gemfire/inbound/cq/gfe-cache.properties"/>
<gfe:cache properties-ref="props" id="c"/>
<!-- tx manager-->
<gfe:transaction-manager cache-ref="c"/>
<!-- region -->
<gfe:replicated-region id="r" name="${region-name}" cache-ref="c" />
</beans>

View File

@@ -1,131 +0,0 @@
/*
* Copyright 2002-2011 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.cq.client;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.*;
import com.gemstone.gemfire.cache.query.CqEvent;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessagingException;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.gemfire.inbound.ContinuousQueryMessageProducer;
import org.springframework.integration.gemfire.inbound.cq.server.CqServerConfiguration;
import javax.annotation.PostConstruct;
/**
* Simple example demonstrating the client side of a continuous query using Gemfire
*
* @author Josh Long
*
*/
@ImportResource("/org/springframework/integration/gemfire/inbound/cq/CqClient-context.xml")
@Configuration
@PropertySource("/org/springframework/integration/gemfire/inbound/cq/common.properties")
@SuppressWarnings("unused")
public class CqClientConfiguration {
static private Log log = LogFactory.getLog(CqClientConfiguration.class);
private String regionName, host, query;
private int port;
@Autowired
private Environment environment;
@Autowired @Qualifier("cqIn")
private MessageChannel messageChannel;
public static void main(String[] args) throws Throwable {
if (log.isInfoEnabled()) {
log.info(String.format("Starting the %s client. Make sure to run the %s server, first.", CqServerConfiguration.class.getName(), CqClientConfiguration.class.getName()));
}
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(CqClientConfiguration.class);
long timeout = 10 * 1000;
long counter = 0;
while (((counter += 1) < timeout)) {
Thread.sleep(1000);
}
}
@PostConstruct
public void setup() throws Throwable {
this.regionName = environment.getProperty("region-name");
this.port = Integer.parseInt(environment.getProperty("port"));
this.host = environment.getProperty("host");
this.query = environment.getProperty("region-query");
}
@Bean
public Object cqServiceActivator() {
return new Object() {
@ServiceActivator
public void handleMessage(Message<CqEvent> eventMessage) throws MessagingException {
CqEvent cqEvent = eventMessage.getPayload();
System.out.println("Received an event from the continuous query adapter: " + cqEvent) ;
}
};
}
@Bean
public ClientCache clientCache() throws Throwable {
return new ClientCacheFactory().create();
}
@Bean
public Region<?, ?> clientRegion() throws Throwable {
ClientRegionFactory<?, ?> clientRegionFactory = clientCache().createClientRegionFactory(ClientRegionShortcut.PROXY);
return clientRegionFactory.create(this.regionName);
}
@Bean
public Pool pool() throws Throwable {
return this.buildPool(this.host, this.port);
}
@Bean
public ContinuousQueryMessageProducer continuousQueryMessageProducer() throws Throwable {
ContinuousQueryMessageProducer mp = new ContinuousQueryMessageProducer(this.clientRegion(), this.pool(), this.query);
mp.setDurable(true);
mp.setOutputChannel(this.messageChannel);
mp.setQueryName("pplQuery");
return mp;
}
protected Pool buildPool(String host, int port) throws Throwable {
return PoolManager.createFactory()
.addServer(host, port)
.setSubscriptionEnabled(true)
.create(host + "Pool");
}
}

View File

@@ -1,116 +0,0 @@
/*
* Copyright 2002-2011 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.cq.server;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.server.CacheServer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.data.gemfire.GemfireTemplate;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import javax.annotation.PostConstruct;
/**
* Demonstrates the server side for a continuous query example. This must be run before
* {@link org.springframework.integration.gemfire.inbound.cq.client.CqClientConfiguration}.
*
* This must also be run in a separate VM as the {@link org.springframework.integration.gemfire.inbound.cq.client.CqClientConfiguration}.
*
* @author Josh Long
*
*/
@PropertySource("org/springframework/integration/gemfire/inbound/cq/common.properties")
@ImportResource("/org/springframework/integration/gemfire/inbound/cq/CqServer-context.xml")
@Configuration
@SuppressWarnings("unused")
public class CqServerConfiguration {
private static Log log = LogFactory.getLog(CqServerConfiguration.class);
@Autowired private Environment environment;
@Value("#{c}") private Cache cache;
@Value("#{r}") private Region<String, ?> region;
private String regionName, host;
private int port;
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(CqServerConfiguration.class);
GemfireTemplate gemfireTemplate = annotationConfigApplicationContext.getBean(GemfireTemplate.class);
TaskScheduler scheduler = annotationConfigApplicationContext.getBean(TaskScheduler.class);
BusyWorkRunnable busyWorkRunnable = new BusyWorkRunnable(gemfireTemplate);
scheduler.scheduleAtFixedRate(busyWorkRunnable, 10 * 1000);
}
@PostConstruct
public void setup() throws Throwable {
host = this.environment.getProperty("host");
regionName = this.environment.getProperty("region-name");
port = Integer.parseInt(this.environment.getProperty("port"));
}
@Bean
public GemfireTemplate gemfireTemplate() {
return new GemfireTemplate(this.region);
}
@Bean
public CacheServer cacheServer() throws Throwable {
CacheServer cacheServer = this.cache.addCacheServer();
cacheServer.setBindAddress(this.host);
cacheServer.setPort(this.port);
cacheServer.start();
return cacheServer;
}
@Bean
public TaskScheduler scheduler() {
return new ThreadPoolTaskScheduler();
}
private static class BusyWorkRunnable implements Runnable {
private GemfireTemplate gemfireTemplate;
private String letters = "abcdefghijk";
public BusyWorkRunnable(GemfireTemplate gemfireTemplate) {
this.gemfireTemplate = gemfireTemplate;
}
public void run() {
for (char c : letters.toCharArray()) {
if (log.isDebugEnabled()) {
log.debug("Adding '" + c + "'");
}
gemfireTemplate.put("" + c, "value-" + c);
}
}
}
}

View File

@@ -11,7 +11,7 @@
<bean class="org.springframework.integration.gemfire.store.messagegroupstore.GemfireMessageGroupStoreTestConfiguration"/>
<context:property-placeholder location="org/springframework/integration/gemfire/inbound/cq/common.properties"/>
<context:property-placeholder location="org/springframework/integration/gemfire/store/messagegroupstore/common.properties"/>
<int:channel id="i"/>
@@ -21,6 +21,6 @@
<int:service-activator input-channel="o" ref="messageGroupStoreActivator" />
<util:properties id="props" location="org/springframework/integration/gemfire/inbound/cq/gfe-cache.properties"/>
<util:properties id="props" location="org/springframework/integration/gemfire/store/messagegroupstore/gfe-cache.properties"/>
</beans>

View File

@@ -12,11 +12,11 @@
<!-- Loggers -->
<logger name="org.springframework">
<level value="warn" />
<level value="debug" />
</logger>
<logger name="org.springframework.integration">
<level value="warn" />
<level value="debug" />
</logger>
<!-- Root Logger -->