SGF-555 - Repository queries on client Regions associated with a Pool configured for a specific server group can lead to a RegionNotFoundException.

(cherry picked from commit 6ee35c488d15d1922477e6813eae9529c15c046b)
Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
John Blum
2016-10-07 22:41:34 -07:00
parent e66baad898
commit 39abc0e331
22 changed files with 1723 additions and 925 deletions

View File

@@ -1,336 +0,0 @@
/*
* Copyright 2010-2013 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.data.gemfire;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.gemfire.repository.sample.User;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.query.SelectResults;
/**
* The GemfireTemplateIntegrationTest class is a test suite of test cases testing the contract and functionality
* of the SDG GemfireTemplate class for wrapping a GemFire Cache Region and performing Cache Region operations.
*
* @author John Blum
* @see org.junit.Test
* @see org.springframework.data.gemfire.GemfireTemplate
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
* @since 1.4.0
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@SuppressWarnings("unused")
public class GemfireTemplateIntegrationTest {
protected static final List<User> TEST_USER_LIST = new ArrayList<User>(11);
static {
TEST_USER_LIST.add(createUser("jonDoe"));
TEST_USER_LIST.add(createUser("janeDoe", false));
TEST_USER_LIST.add(createUser("pieDoe", false));
TEST_USER_LIST.add(createUser("cookieDoe"));
TEST_USER_LIST.add(createUser("jackHandy"));
TEST_USER_LIST.add(createUser("mandyHandy", false));
TEST_USER_LIST.add(createUser("randyHandy", false));
TEST_USER_LIST.add(createUser("sandyHandy"));
TEST_USER_LIST.add(createUser("imaPigg"));
}
@Resource(name = "Users")
private Region<String, User> users;
@Autowired
private GemfireTemplate usersTemplate;
protected static User createUser(final String username) {
return createUser(username, true);
}
protected static User createUser(final String username, final Boolean active) {
return createUser(username, String.format("%1$s@companyx.com", username), Calendar.getInstance(), active);
}
protected static User createUser(final String username, final String email, final Calendar since, final Boolean active) {
User user = new User(username);
user.setActive(Boolean.TRUE.equals(active));
user.setEmail(email);
user.setSince(since);
return user;
}
protected String getKey(final User user) {
return (user != null ? user.getUsername() : null);
}
protected User getUser(final String username) {
for (User user : TEST_USER_LIST) {
if (user.getUsername().equals(username)) {
return user;
}
}
return null;
}
protected List<User> getUsers(final String... usernames) {
List<User> users = new ArrayList<User>(usernames.length);
List<String> usernameList = Arrays.asList(usernames);
for (User user : TEST_USER_LIST) {
if (usernameList.contains(user.getUsername())) {
users.add(user);
}
}
return users;
}
protected Map<String, User> getUsersAsMap(final User... users) {
Map<String, User> userMap = new HashMap<String, User>(users.length);
for (User user : users) {
userMap.put(getKey(user), user);
}
return userMap;
}
protected void assertNullEquals(final Object value1, final Object value2) {
Assert.assertTrue(value1 == null ? value2 == null : value1.equals(value2));
}
@Before
public void setup() {
assertNotNull("The 'Users' Region was not properly configured and initialized!", users);
if (users.isEmpty()) {
for (User user : TEST_USER_LIST) {
users.put(getKey(user), user);
}
assertFalse(users.isEmpty());
assertEquals(TEST_USER_LIST.size(), users.size());
}
}
@Test
public void testContainsKey() {
assertTrue(usersTemplate.containsKey(getKey(getUser("jonDoe"))));
assertFalse(usersTemplate.containsKey("dukeNukem"));
}
@Test
@Ignore
public void testContainsKeyOnServer() {
assertTrue(usersTemplate.containsKeyOnServer(getKey(getUser("jackHandy"))));
assertFalse(usersTemplate.containsKeyOnServer("maxPayne"));
}
@Test
public void testContainsValue() {
assertTrue(usersTemplate.containsValue(getUser("pieDoe")));
assertFalse(usersTemplate.containsValue(createUser("pieDough")));
}
@Test
public void testContainsValueForKey() {
assertTrue(usersTemplate.containsValueForKey(getKey(getUser("cookieDoe"))));
assertFalse(usersTemplate.containsValueForKey("chocolateChipCookieDoe"));
}
@Test
public void testCreate() {
User bartSimpson = createUser("bartSimpson");
usersTemplate.create(getKey(bartSimpson), bartSimpson);
assertTrue(users.containsKey(getKey(bartSimpson)));
assertTrue(users.containsValueForKey(getKey(bartSimpson)));
assertTrue(users.containsValue(bartSimpson));
assertEquals(bartSimpson, users.get(getKey(bartSimpson)));
}
@Test
public void testGet() {
assertEquals(users.get(getKey(getUser("imaPigg"))), usersTemplate.get(getKey(getUser("imaPigg"))));
assertNullEquals(users.get("mrT"), usersTemplate.get("mrT"));
}
@Test
public void testPut() {
User peterGriffon = createUser("peterGriffon");
assertNull(usersTemplate.put(getKey(peterGriffon), peterGriffon));
assertEquals(peterGriffon, users.get(getKey(peterGriffon)));
}
@Test
public void testPutIfAbsent() {
User stewieGriffon = createUser("stewieGriffon");
assertFalse(users.containsValue(stewieGriffon));
assertNull(usersTemplate.putIfAbsent(getKey(stewieGriffon), stewieGriffon));
assertTrue(users.containsValue(stewieGriffon));
assertEquals(stewieGriffon, usersTemplate.putIfAbsent(getKey(stewieGriffon), createUser("megGriffon")));
assertEquals(stewieGriffon, users.get(getKey(stewieGriffon)));
}
@Test
public void testRemove() {
User mandyHandy = users.get(getKey(getUser("mandyHandy")));
assertNotNull(mandyHandy);
assertEquals(mandyHandy, usersTemplate.remove(getKey(mandyHandy)));
assertFalse(users.containsKey(getKey(mandyHandy)));
assertFalse(users.containsValue(mandyHandy));
assertFalse(users.containsKey("loisGriffon"));
assertNull(usersTemplate.remove("loisGriffon"));
assertFalse(users.containsKey("loisGriffon"));
}
@Test
public void testReplace() {
User randyHandy = users.get(getKey(getUser("randyHandy")));
User lukeFluke = createUser("lukeFluke");
User chrisGriffon = createUser("chrisGriffon");
assertNotNull(randyHandy);
assertEquals(randyHandy, usersTemplate.replace(getKey(randyHandy), lukeFluke));
assertEquals(lukeFluke, users.get(getKey(randyHandy)));
assertFalse(users.containsValue(randyHandy));
assertFalse(users.containsValue(chrisGriffon));
assertNull(usersTemplate.replace(getKey(chrisGriffon), chrisGriffon));
assertFalse(users.containsValue(chrisGriffon));
}
@Test
public void testReplaceOldValueWithNewValue() {
User jackHandy = getUser("jackHandy");
User imaPigg = getUser("imaPigg");
assertTrue(users.containsValue(jackHandy));
assertFalse(usersTemplate.replace(getKey(jackHandy), null, imaPigg));
assertTrue(users.containsValue(jackHandy));
assertEquals(jackHandy, users.get(getKey(jackHandy)));
assertTrue(usersTemplate.replace(getKey(jackHandy), jackHandy, imaPigg));
assertFalse(users.containsValue(jackHandy));
assertEquals(imaPigg, users.get(getKey(jackHandy)));
}
@Test
public void testGetAllReturnsNoResults() {
List<String> keys = Arrays.asList("keyOne", "keyTwo", "keyThree");
Map<String, User> actualUserMapping = usersTemplate.getAll(keys);
Map<String, User> expectedUserMapping = users.getAll(keys);
assertEquals(expectedUserMapping, actualUserMapping);
}
@Test
public void testGetAllReturnsResults() {
List<String> keys = Arrays.asList(getKey(getUser("jonDoe")), getKey(getUser("pieDoe")));
Map<String, User> actualUserMapping = usersTemplate.getAll(keys);
Map<String, User> expectedUserMapping = users.getAll(keys);
assertEquals(actualUserMapping, expectedUserMapping);
}
@Test
public void testPutAll() {
User batMan = createUser("batMap");
User spiderMan = createUser("spiderMan");
User superMan = createUser("superMan");
Map<String, User> userMap = getUsersAsMap(batMan, spiderMan, superMan);
assertFalse(users.keySet().containsAll(userMap.keySet()));
assertFalse(users.values().containsAll(userMap.values()));
usersTemplate.putAll(userMap);
assertTrue(users.keySet().containsAll(userMap.keySet()));
assertTrue(users.values().containsAll(userMap.values()));
}
@Test
public void testQuery() {
SelectResults<User> queryResults = usersTemplate.query("username LIKE '%Doe'");
assertNotNull(queryResults);
List<User> queriedUsers = queryResults.asList();
assertNotNull(queriedUsers);
assertFalse(queriedUsers.isEmpty());
assertEquals(4, queriedUsers.size());
assertTrue(queriedUsers.containsAll(getUsers("jonDoe", "janeDoe", "pieDoe", "cookieDoe")));
}
@Test
public void testFind() {
SelectResults<User> findResults = usersTemplate.find("SELECT u FROM /Users u WHERE u.username LIKE $1 AND u.active = $2", "%Doe", true);
assertNotNull(findResults);
List<User> usersFound = findResults.asList();
assertNotNull(usersFound);
assertFalse(usersFound.isEmpty());
assertEquals(2, usersFound.size());
assertTrue(usersFound.containsAll(getUsers("jonDoe", "cookieDoe")));
}
@Test
public void testFindUniqueReturnsResult() {
User jonDoe = usersTemplate.findUnique("SELECT u FROM /Users u WHERE u.username = $1", "jonDoe");
assertNotNull(jonDoe);
assertEquals(getUser("jonDoe"), jonDoe);
}
@Test(expected = InvalidDataAccessApiUsageException.class)
public void testFindUniqueReturnsNoResult() {
usersTemplate.findUnique("SELECT u FROM /Users u WHERE u.username = $1", "benDover");
}
}

View File

@@ -0,0 +1,399 @@
/*
* Copyright 2010-2013 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.data.gemfire;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.is;
import static org.junit.Assume.assumeThat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.annotation.Resource;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.query.SelectResults;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.gemfire.repository.sample.User;
import org.springframework.data.gemfire.util.CacheUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Integration tests for {@link GemfireTemplate}.
*
* @author John Blum
* @see org.junit.Test
* @see org.springframework.data.gemfire.GemfireTemplate
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.junit4.SpringJUnit4ClassRunner
* @since 1.4.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@SuppressWarnings("unused")
public class GemfireTemplateIntegrationTests {
protected static final String DEFAULT_GEMFIRE_LOG_LEVEL = "warning";
protected static final List<User> TEST_USERS = new ArrayList<User>(9);
static {
TEST_USERS.add(newUser("jonDoe"));
TEST_USERS.add(newUser("janeDoe", false));
TEST_USERS.add(newUser("pieDoe", false));
TEST_USERS.add(newUser("cookieDoe"));
TEST_USERS.add(newUser("jackHandy"));
TEST_USERS.add(newUser("mandyHandy", false));
TEST_USERS.add(newUser("randyHandy", false));
TEST_USERS.add(newUser("sandyHandy"));
TEST_USERS.add(newUser("imaPigg"));
}
@Autowired
private GemFireCache gemfireCache;
@Autowired
private GemfireTemplate usersTemplate;
@Resource(name = "Users")
private Region<String, User> users;
protected static User newUser(String username) {
return newUser(username, true);
}
protected static User newUser(String username, Boolean active) {
return newUser(username, String.format("%1$s@companyx.com", username), Calendar.getInstance(), active);
}
protected static User newUser(String username, String email, Calendar since, Boolean active) {
User user = new User(username);
user.setActive(Boolean.TRUE.equals(active));
user.setEmail(email);
user.setSince(since);
return user;
}
protected String getKey(User user) {
return (user != null ? user.getUsername() : null);
}
protected User getUser(String username) {
for (User user : TEST_USERS) {
if (user.getUsername().equals(username)) {
return user;
}
}
return null;
}
protected List<User> getUsers(String... usernames) {
List<String> usernameList = Arrays.asList(usernames);
List<User> users = new ArrayList<User>(usernames.length);
for (User user : TEST_USERS) {
if (usernameList.contains(user.getUsername())) {
users.add(user);
}
}
return users;
}
protected Map<String, User> getUsersAsMap(String... usernames) {
return getUsersAsMap(getUsers(usernames));
}
protected Map<String, User> getUsersAsMap(User... users) {
return getUsersAsMap(Arrays.asList(users));
}
protected Map<String, User> getUsersAsMap(Iterable<User> users) {
Map<String, User> userMap = new HashMap<String, User>();
for (User user : users) {
userMap.put(getKey(user), user);
}
return userMap;
}
protected void assertNullEquals(Object value1, Object value2) {
assertThat(value1 == null ? value2 == null : value1.equals(value2)).isTrue();
}
@Before
public void setup() {
assertThat(users).isNotNull();
if (users.isEmpty()) {
for (User user : TEST_USERS) {
users.put(getKey(user), user);
}
assertThat(users.isEmpty()).isFalse();
assertThat(users.size()).isEqualTo(TEST_USERS.size());
}
}
@Test
public void containsKey() {
assertThat(usersTemplate.containsKey(getKey(getUser("jonDoe")))).isTrue();
assertThat(usersTemplate.containsKey("dukeNukem")).isFalse();
}
@Test
public void containsKeyOnServer() {
assumeThat(CacheUtils.isClient(gemfireCache), is(true));
assertThat(usersTemplate.containsKeyOnServer(getKey(getUser("jackHandy")))).isTrue();
assertThat(usersTemplate.containsKeyOnServer("maxPayne")).isFalse();
}
@Test
public void containsValue() {
assertThat(usersTemplate.containsValue(getUser("pieDoe"))).isTrue();
assertThat(usersTemplate.containsValue(newUser("pieDough"))).isFalse();
}
@Test
public void containsValueForKey() {
assertThat(usersTemplate.containsValueForKey(getKey(getUser("cookieDoe")))).isTrue();
assertThat(usersTemplate.containsValueForKey("chocolateChipCookieDoe")).isFalse();
}
@Test
public void create() {
User bartSimpson = newUser("bartSimpson");
usersTemplate.create(getKey(bartSimpson), bartSimpson);
assertThat(users.containsKey(getKey(bartSimpson))).isTrue();
assertThat(users.containsValueForKey(getKey(bartSimpson))).isTrue();
assertThat(users.containsValue(bartSimpson)).isTrue();
assertThat(users.get(getKey(bartSimpson))).isEqualTo(bartSimpson);
}
@Test
public void get() {
String key = getKey(getUser("imaPigg"));
assertThat(usersTemplate.get(key)).isEqualTo(users.get(key));
assertNullEquals(users.get("mrT"), usersTemplate.get("mrT"));
}
@Test
public void put() {
User peterGriffon = newUser("peterGriffon");
assertThat(usersTemplate.put(getKey(peterGriffon), peterGriffon)).isNull();
assertThat(users.get(getKey(peterGriffon))).isEqualTo(peterGriffon);
}
@Test
public void putIfAbsent() {
User stewieGriffon = newUser("stewieGriffon");
assertThat(users.containsValue(stewieGriffon)).isFalse();
assertThat(usersTemplate.putIfAbsent(getKey(stewieGriffon), stewieGriffon)).isNull();
assertThat(users.containsValue(stewieGriffon)).isTrue();
assertThat(usersTemplate.putIfAbsent(getKey(stewieGriffon), newUser("megGriffon"))).isEqualTo(stewieGriffon);
assertThat(users.get(getKey(stewieGriffon))).isEqualTo(stewieGriffon);
}
@Test
public void remove() {
User mandyHandy = users.get(getKey(getUser("mandyHandy")));
assertThat(mandyHandy).isNotNull();
assertThat(usersTemplate.remove(getKey(mandyHandy))).isEqualTo(mandyHandy);
assertThat(users.containsKey(getKey(mandyHandy))).isFalse();
assertThat(users.containsValue(mandyHandy)).isFalse();
assertThat(users.containsKey("loisGriffon")).isFalse();
assertThat(usersTemplate.remove("loisGriffon")).isNull();
assertThat(users.containsKey("loisGriffon")).isFalse();
}
@Test
public void replace() {
User randyHandy = users.get(getKey(getUser("randyHandy")));
User lukeFluke = newUser("lukeFluke");
User chrisGriffon = newUser("chrisGriffon");
assertThat(randyHandy).isNotNull();
assertThat(usersTemplate.replace(getKey(randyHandy), lukeFluke)).isEqualTo(randyHandy);
assertThat(users.get(getKey(randyHandy))).isEqualTo(lukeFluke);
assertThat(users.containsValue(randyHandy)).isFalse();
assertThat(users.containsValue(chrisGriffon)).isFalse();
assertThat(usersTemplate.replace(getKey(chrisGriffon), chrisGriffon)).isNull();
assertThat(users.containsValue(chrisGriffon)).isFalse();
}
@Test
public void replaceOldValueWithNewValue() {
User jackHandy = getUser("jackHandy");
User imaPigg = getUser("imaPigg");
assertThat(users.containsValue(jackHandy)).isTrue();
assertThat(usersTemplate.replace(getKey(jackHandy), null, imaPigg)).isFalse();
assertThat(users.containsValue(jackHandy)).isTrue();
assertThat(users.get(getKey(jackHandy))).isEqualTo(jackHandy);
assertThat(usersTemplate.replace(getKey(jackHandy), jackHandy, imaPigg)).isTrue();
assertThat(users.containsValue(jackHandy)).isFalse();
assertThat(users.get(getKey(jackHandy))).isEqualTo(imaPigg);
}
@Test
public void getAllReturnsNoResults() {
List<String> keys = Arrays.asList("keyOne", "keyTwo", "keyThree");
Map<String, User> users = usersTemplate.getAll(keys);
assertThat(users).isNotNull();
assertThat(users).isEqualTo(this.users.getAll(keys));
}
@Test
public void getAllReturnsResults() {
Map<String, User> users = usersTemplate.getAll(Arrays.asList(
getKey(getUser("jonDoe")), getKey(getUser("pieDoe"))));
assertThat(users).isNotNull();
assertThat(users).isEqualTo(getUsersAsMap(getUser("jonDoe"), getUser("pieDoe")));
}
@Test
public void putAll() {
User batMan = newUser("batMan");
User spiderMan = newUser("spiderMan");
User superMan = newUser("superMan");
Map<String, User> userMap = getUsersAsMap(batMan, spiderMan, superMan);
assertThat(users.keySet().containsAll(userMap.keySet())).isFalse();
assertThat(users.values().containsAll(userMap.values())).isFalse();
usersTemplate.putAll(userMap);
assertThat(users.keySet().containsAll(userMap.keySet())).isTrue();
assertThat(users.values().containsAll(userMap.values())).isTrue();
}
@Test
public void query() {
SelectResults<User> queryResults = usersTemplate.query("username LIKE '%Doe'");
assertThat(queryResults).isNotNull();
List<User> usersFound = queryResults.asList();
assertThat(usersFound).isNotNull();
assertThat(usersFound.size()).isEqualTo(4);
assertThat(usersFound.containsAll(getUsers("jonDoe", "janeDoe", "pieDoe", "cookieDoe"))).isTrue();
}
@Test
public void find() {
SelectResults<User> findResults = usersTemplate.find("SELECT u FROM /Users u WHERE u.username LIKE $1 AND u.active = $2", "%Doe", true);
assertThat(findResults).isNotNull();
List<User> usersFound = findResults.asList();
assertThat(usersFound).isNotNull();
assertThat(usersFound.size()).isEqualTo(2);
assertThat(usersFound.containsAll(getUsers("jonDoe", "cookieDoe"))).isTrue();
}
@Test
public void findUniqueReturnsResult() {
User jonDoe = usersTemplate.findUnique("SELECT u FROM /Users u WHERE u.username = $1", "jonDoe");
assertThat(jonDoe).isNotNull();
assertThat(jonDoe).isEqualTo(getUser("jonDoe"));
}
@Test(expected = InvalidDataAccessApiUsageException.class)
public void findUniqueReturnsNoResult() {
usersTemplate.findUnique("SELECT u FROM /Users u WHERE u.username = $1", "benDover");
}
@Test(expected = InvalidDataAccessApiUsageException.class)
public void findUnqiueReturnsTooManyResults() {
usersTemplate.findUnique("SELECT u FROM /Users u WHERE u.username LIKE $1", "%Doe");
}
@Configuration
static class GemfireTemplateConfiguration {
Properties gemfireProperties() {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", applicationName());
gemfireProperties.setProperty("mcast-port", "0");
gemfireProperties.setProperty("log-level", logLevel());
return gemfireProperties;
}
String applicationName() {
return GemfireTemplateIntegrationTests.class.getName();
}
String logLevel() {
return System.getProperty("gemfire.log-level", DEFAULT_GEMFIRE_LOG_LEVEL);
}
@Bean
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(false);
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
@Bean(name = "Users")
LocalRegionFactoryBean<Object, Object> usersRegion(GemFireCache gemfireCache) {
LocalRegionFactoryBean<Object, Object> usersRegion = new LocalRegionFactoryBean<Object, Object>();
usersRegion.setCache(gemfireCache);
usersRegion.setClose(false);
usersRegion.setPersistent(false);
return usersRegion;
}
@Bean
GemfireTemplate usersRegionTemplate(Region<Object, Object> simple) {
return new GemfireTemplate(simple);
}
}
}

View File

@@ -0,0 +1,401 @@
/*
* Copyright 2016 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.data.gemfire;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
import com.gemstone.gemfire.cache.client.Pool;
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.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.client.PoolFactoryBean;
import org.springframework.data.gemfire.mapping.Region;
import org.springframework.data.gemfire.process.ProcessExecutor;
import org.springframework.data.gemfire.process.ProcessWrapper;
import org.springframework.data.gemfire.server.CacheServerFactoryBean;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.data.gemfire.support.ConnectionEndpointList;
import org.springframework.data.gemfire.test.support.ClientServerIntegrationTestsSupport;
import org.springframework.data.gemfire.util.PropertiesBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
/**
* Integrations tests for {@link GemfireTemplate} testing proper function and behavior of executing (OQL) queries
* from a cache client application using the {@link GemfireTemplate} to a cluster of GemFire servers that have
* been grouped according to business function and data access, primarily to distribute the load.
*
* Each GemFire {@link Pool} is configured to target a specific server group. Each group of servers in the cluster
* defines specific {@link Region Regions} to manage data independently and separately from other data that might
* garner high frequency access.
*
* Spring Data GemFire's {@link GemfireTemplate} should intelligently employ the right
* {@link com.gemstone.gemfire.cache.query.QueryService} configured with the {@link Region Region's} {@link Pool}
* meta-data when executing the query in order to ensure the right servers containing the {@link Region Region's}
* with the data of interest are targeted.
*
* @author John Blum
* @see org.springframework.data.gemfire.GemfireTemplate
* @see <a href="https://jira.spring.io/browse/SGF-555">Repository queries on client Regions associated with a Pool configured with a specified server group can lead to a RegionNotFoundException.</a>
* @since 1.9.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes =
GemfireTemplateQueriesOnGroupedPooledClientCacheRegionsIntegrationTests.GemFireClientCacheConfiguration.class)
@SuppressWarnings("unused")
public class GemfireTemplateQueriesOnGroupedPooledClientCacheRegionsIntegrationTests
extends ClientServerIntegrationTestsSupport{
protected static final String DEFAULT_GEMFIRE_LOG_LEVEL = "warning";
private static ProcessWrapper serverOne;
private static ProcessWrapper serverTwo;
@Autowired
@Qualifier("catsTemplate")
private GemfireTemplate catsTemplate;
@Autowired
@Qualifier("dogsTemplate")
private GemfireTemplate dogsTemplate;
@BeforeClass
public static void setupGemFireCluster() throws Exception {
serverOne = ProcessExecutor.launch(createDirectory("serverOne"), GemFireCacheServerOneConfiguration.class);
waitForCacheServerToStart("localhost", 41414);
serverTwo = ProcessExecutor.launch(createDirectory("serverTwo"), GemFireCacheServerTwoConfiguration.class);
waitForCacheServerToStart("localhost", 42424);
}
@AfterClass
public static void shutdownGemFireCluster() {
serverOne.stop();
serverTwo.stop();
}
@Test
public void findsAllCats() {
List<String> catNames = catsTemplate.<String>find("SELECT c.name FROM /Cats c").asList();
assertThat(catNames).isNotNull();
assertThat(catNames.size()).isEqualTo(5);
assertThat(catNames).containsAll(Arrays.asList("Grey", "Patchit", "Tyger", "Molly", "Sammy"));
}
@Test
public void findsAllDogs() {
List<String> dogNames = dogsTemplate.<String>find("SELECT d.name FROM /Dogs d").asList();
assertThat(dogNames).isNotNull();
assertThat(dogNames.size()).isEqualTo(2);
assertThat(dogNames).containsAll(Arrays.asList("Spuds", "Maha"));
}
@Data
@Region("Cats")
@RequiredArgsConstructor(staticName = "newCat")
static class Cat {
@Id @NonNull private String name;
}
@Data
@Region("Dogs")
@RequiredArgsConstructor(staticName = "newDog")
static class Dog {
@Id @NonNull private String name;
}
@Configuration
static class GemFireClientCacheConfiguration {
Properties gemfireProperties() {
return PropertiesBuilder.create()
.setProperty("name", applicationName())
.setProperty("log-level", logLevel())
.build();
}
String applicationName() {
return GemFireClientCacheConfiguration.class.getName();
}
String logLevel() {
return System.getProperty("gemfire.log.level", DEFAULT_GEMFIRE_LOG_LEVEL);
}
@Bean
ClientCacheFactoryBean gemfireCache() {
ClientCacheFactoryBean gemfireCache = new ClientCacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setPoolName("ServerOnePool");
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
@Bean(name = "ServerOnePool")
PoolFactoryBean serverOnePool() {
PoolFactoryBean serverOnePool = new PoolFactoryBean();
serverOnePool.setMaxConnections(2);
serverOnePool.setPingInterval(TimeUnit.SECONDS.toMillis(5));
serverOnePool.setReadTimeout(Long.valueOf(TimeUnit.SECONDS.toMillis(20)).intValue());
serverOnePool.setRetryAttempts(1);
serverOnePool.setServerGroup("serverOne");
serverOnePool.setLocators(ConnectionEndpointList.from(newConnectionEndpoint("localhost", 11235)));
return serverOnePool;
}
@Bean(name = "ServerTwoPool")
PoolFactoryBean serverTwoPool() {
PoolFactoryBean serverOnePool = new PoolFactoryBean();
serverOnePool.setMaxConnections(2);
serverOnePool.setPingInterval(TimeUnit.SECONDS.toMillis(5));
serverOnePool.setReadTimeout(Long.valueOf(TimeUnit.SECONDS.toMillis(20)).intValue());
serverOnePool.setRetryAttempts(1);
serverOnePool.setServerGroup("serverTwo");
serverOnePool.setLocators(ConnectionEndpointList.from(newConnectionEndpoint("localhost", 11235)));
return serverOnePool;
}
@Bean(name = "Cats")
ClientRegionFactoryBean<String, Cat> catsRegion(GemFireCache gemfireCache,
@Qualifier("ServerOnePool") Pool serverOnePool) {
ClientRegionFactoryBean<String, Cat> catsRegion = new ClientRegionFactoryBean<String, Cat>();
catsRegion.setCache(gemfireCache);
catsRegion.setClose(false);
catsRegion.setPoolName(serverOnePool.getName());
catsRegion.setShortcut(ClientRegionShortcut.PROXY);
return catsRegion;
}
@Bean(name = "Dogs")
ClientRegionFactoryBean<String, Cat> dogsRegion(GemFireCache gemfireCache,
@Qualifier("ServerTwoPool") Pool serverTwoPool) {
ClientRegionFactoryBean<String, Cat> dogsRegion = new ClientRegionFactoryBean<String, Cat>();
dogsRegion.setCache(gemfireCache);
dogsRegion.setClose(false);
dogsRegion.setPoolName(serverTwoPool.getName());
dogsRegion.setShortcut(ClientRegionShortcut.PROXY);
return dogsRegion;
}
@Bean
@DependsOn("Cats")
GemfireTemplate catsTemplate(GemFireCache gemfireCache) {
return new GemfireTemplate(gemfireCache.getRegion("Cats"));
}
@Bean
@DependsOn("Dogs")
GemfireTemplate dogsTemplate(GemFireCache gemfireCache) {
return new GemfireTemplate(gemfireCache.getRegion("Dogs"));
}
ConnectionEndpoint newConnectionEndpoint(String host, int port) {
return new ConnectionEndpoint(host, port);
}
}
static abstract class AbstractGemFireCacheServerConfiguration {
Properties gemfireProperties() {
return PropertiesBuilder.create()
.setProperty("name", applicationName())
.setProperty("mcast-port", "0")
.setProperty("log-level", logLevel())
.setProperty("locators", "localhost[11235]")
.setProperty("groups", groups())
.setProperty("start-locator", startLocator())
.build();
}
String applicationName() {
return getClass().getName();
}
abstract String groups();
String logLevel() {
return System.getProperty("gemfire.log.level", DEFAULT_GEMFIRE_LOG_LEVEL);
}
String startLocator() {
return "";
}
@Bean
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
@Bean
CacheServerFactoryBean gemfireCacheServer(Cache gemfireCache) {
CacheServerFactoryBean gemfireCacheServer = new CacheServerFactoryBean();
gemfireCacheServer.setAutoStartup(true);
gemfireCacheServer.setCache(gemfireCache);
gemfireCacheServer.setMaxTimeBetweenPings(Long.valueOf(TimeUnit.SECONDS.toMillis(60)).intValue());
gemfireCacheServer.setPort(cacheServerPort());
return gemfireCacheServer;
}
abstract int cacheServerPort();
}
@Configuration
@SuppressWarnings("all")
static class GemFireCacheServerOneConfiguration extends AbstractGemFireCacheServerConfiguration {
@Resource(name = "Cats")
private com.gemstone.gemfire.cache.Region<String, Cat> cats;
Cat save(Cat cat) {
cats.put(cat.getName(), cat);
return cat;
}
@PostConstruct
public void postConstruct() {
save(Cat.newCat("Grey"));
save(Cat.newCat("Patchit"));
save(Cat.newCat("Tyger"));
save(Cat.newCat("Molly"));
save(Cat.newCat("Sammy"));
}
@Override
int cacheServerPort() {
return 41414;
}
@Override
String groups() {
return "serverOne";
}
@Override
String startLocator() {
return "localhost[11235]";
}
@Bean(name = "Cats")
LocalRegionFactoryBean catsRegion(Cache gemfireCache) {
LocalRegionFactoryBean catsRegion = new LocalRegionFactoryBean();
catsRegion.setCache(gemfireCache);
catsRegion.setClose(false);
catsRegion.setPersistent(false);
return catsRegion;
}
public static void main(String[] args) {
new AnnotationConfigApplicationContext(GemFireCacheServerOneConfiguration.class)
.registerShutdownHook();
}
}
@Configuration
@SuppressWarnings("all")
static class GemFireCacheServerTwoConfiguration extends AbstractGemFireCacheServerConfiguration {
@Resource(name = "Dogs")
private com.gemstone.gemfire.cache.Region<String, Dog> dogs;
Dog save(Dog dog) {
dogs.put(dog.getName(), dog);
return dog;
}
@PostConstruct
public void postConstruct() {
save(Dog.newDog("Spuds"));
save(Dog.newDog("Maha"));
}
@Override
int cacheServerPort() {
return 42424;
}
@Override
String groups() {
return "serverTwo";
}
@Bean(name = "Dogs")
LocalRegionFactoryBean<String, Dog> dogsRegion(Cache gemfireCache) {
LocalRegionFactoryBean<String, Dog> dogsRegion = new LocalRegionFactoryBean<String, Dog>();
dogsRegion.setCache(gemfireCache);
dogsRegion.setClose(false);
dogsRegion.setPersistent(false);
return dogsRegion;
}
public static void main(String[] args) {
new AnnotationConfigApplicationContext(GemFireCacheServerTwoConfiguration.class)
.registerShutdownHook();
}
}
}

View File

@@ -1,240 +0,0 @@
/*
* Copyright 2011-2013 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.data.gemfire;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Resource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.gemfire.test.AbstractMockerySupport;
import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.gemstone.gemfire.GemFireCheckedException;
import com.gemstone.gemfire.GemFireException;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.query.FunctionDomainException;
import com.gemstone.gemfire.cache.query.NameResolutionException;
import com.gemstone.gemfire.cache.query.Query;
import com.gemstone.gemfire.cache.query.QueryInvocationTargetException;
import com.gemstone.gemfire.cache.query.QueryService;
import com.gemstone.gemfire.cache.query.SelectResults;
import com.gemstone.gemfire.cache.query.TypeMismatchException;
/**
* The GemfireTemplateTest class is a test suite of test cases testing the contract and functionality of the SDG
* GemfireTemplate class.
*
* @author Costin Leau
* @author David Turanski
* @author John Blum
* @see org.junit.Test
* @see org.junit.runner.RunWith
* @see org.springframework.data.gemfire.GemfireTemplate
* @see org.springframework.data.gemfire.test.AbstractMockerySupport
* @see org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer
* @see org.springframework.test.context.ContextConfiguration
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "basic-template.xml", initializers = GemfireTestApplicationContextInitializer.class)
@SuppressWarnings("unused")
public class GemfireTemplateTest extends AbstractMockerySupport {
private static final String MULTI_QUERY = "SELECT * FROM /simple";
private static final String SINGLE_QUERY = "(SELECT * FROM /simple).size";
@Autowired
private GemfireTemplate template;
@Resource(name = "simple")
private Region<?, ?> simple;
@Before
@SuppressWarnings("rawtypes")
public void setUp() throws FunctionDomainException, TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
if (isMocking()) {
QueryService queryService = simple.getRegionService().getQueryService();
Query singleQuery = mock(Query.class);
when(singleQuery.execute(any(Object[].class))).thenReturn(0);
when(queryService.newQuery(SINGLE_QUERY)).thenReturn(singleQuery);
Query multipleQuery = mock(Query.class);
SelectResults selectResults = mock(SelectResults.class);
when(multipleQuery.execute(any(Object[].class))).thenReturn(selectResults);
when(queryService.newQuery(MULTI_QUERY)).thenReturn(multipleQuery);
}
}
@After
public void tearDown() {
template.setExposeNativeRegion(false);
}
@Test
public void testConstructWithNonNullRegion() {
GemfireTemplate localTemplate = new GemfireTemplate(simple);
assertNotNull(localTemplate);
assertSame(simple, localTemplate.getRegion());
assertFalse(localTemplate.isExposeNativeRegion());
}
@Test(expected = IllegalArgumentException.class)
public void testConstructWithNullRegion() {
try {
new GemfireTemplate(null);
}
catch (IllegalArgumentException expected) {
assertEquals("The GemFire Cache Region is required.", expected.getMessage());
throw expected;
}
}
@Test
public void testExecuteUsingNativeRegion() {
template.setExposeNativeRegion(true);
assertTrue(template.isExposeNativeRegion());
assertSame(simple, template.getRegion());
final AtomicBoolean callbackInvoked = new AtomicBoolean(false);
template.execute(new GemfireCallback<Object>() {
@Override
public Object doInGemfire(final Region<?, ?> region) throws GemFireCheckedException, GemFireException {
callbackInvoked.set(true);
assertSame(simple, region);
return null;
}
});
assertTrue(callbackInvoked.get());
}
@Test
public void testExecuteUsingProxyRegion() {
assertFalse(template.isExposeNativeRegion());
final AtomicBoolean callbackInvoked = new AtomicBoolean(false);
template.execute(new GemfireCallback<Object>() {
@Override
public Object doInGemfire(final Region<?, ?> region) throws GemFireCheckedException, GemFireException {
callbackInvoked.set(true);
assertNotSame(simple, region);
return null;
}
});
assertTrue(callbackInvoked.get());
}
@Test(expected = InvalidDataAccessApiUsageException.class)
public void testFindMultiException() throws Exception {
template.find(SINGLE_QUERY);
}
@Test(expected = InvalidDataAccessApiUsageException.class)
public void testFindMultiOne() throws Exception {
template.findUnique(MULTI_QUERY);
}
@Test
public void testFind() throws Exception {
assertNotNull(template.find(MULTI_QUERY));
}
@Test
public void testFindUnique() throws Exception {
assertEquals(0, template.findUnique(SINGLE_QUERY));
}
@Test
@SuppressWarnings("unchecked")
public void testLookupQueryService() {
ClientCache mockClientCache = mock(ClientCache.class, "testLookupQueryService.ClientCache");
QueryService mockQueryService = mock(QueryService.class, "testLookupQueryService.QueryService");
Region<Object, Object> mockRegion = mock(Region.class, "testLookupQueryService.Region");
when(mockRegion.getRegionService()).thenReturn(mockClientCache);
when(mockClientCache.getQueryService()).thenReturn(mockQueryService);
GemfireTemplate localTemplate = new GemfireTemplate(mockRegion) {
@Override boolean isLocalWithNoServerProxy(final Region<?, ?> region) {
return false;
}
};
assertSame(mockQueryService, localTemplate.lookupQueryService(mockRegion));
verify(mockRegion, times(2)).getRegionService();
verify(mockClientCache, times(1)).getQueryService();
verify(mockClientCache, never()).getLocalQueryService();
}
@Test
@SuppressWarnings("unchecked")
public void testLookupLocalQueryService() {
ClientCache mockClientCache = mock(ClientCache.class, "testLookupLocalQueryService.ClientCache");
QueryService mockQueryService = mock(QueryService.class, "testLookupLocalQueryService.QueryService");
Region<Object, Object> mockRegion = mock(Region.class, "testLookupLocalQueryService.Region");
RegionAttributes<Object, Object> mockRegionAttributes = mock(RegionAttributes.class, "testLookupLocalQueryService.RegionAttributes");
when(mockClientCache.getLocalQueryService()).thenReturn(mockQueryService);
when(mockRegion.getRegionService()).thenReturn(mockClientCache);
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
when(mockRegionAttributes.getScope()).thenReturn(Scope.LOCAL);
GemfireTemplate localTemplate = new GemfireTemplate(mockRegion) {
@Override boolean isLocalWithNoServerProxy(final Region<?, ?> region) {
return true;
}
};
assertSame(mockQueryService, localTemplate.lookupQueryService(mockRegion));
verify(mockClientCache, never()).getQueryService();
verify(mockClientCache, times(1)).getLocalQueryService();
verify(mockRegion, times(2)).getRegionService();
verify(mockRegionAttributes, times(1)).getScope();
}
}

View File

@@ -0,0 +1,356 @@
/*
* Copyright 2011-2013 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.data.gemfire;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicBoolean;
import com.gemstone.gemfire.GemFireCheckedException;
import com.gemstone.gemfire.GemFireException;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.query.Query;
import com.gemstone.gemfire.cache.query.QueryService;
import com.gemstone.gemfire.cache.query.SelectResults;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.gemfire.test.support.AbstractUnitAndIntegrationTestsWithMockSupport;
/**
* Unit tests for {@link GemfireTemplate}
*
* @author Costin Leau
* @author David Turanski
* @author John Blum
* @see org.junit.Test
* @see org.mockito.Mock
* @see org.mockito.Mockito
* @see org.mockito.runners.MockitoJUnitRunner
* @see org.springframework.data.gemfire.GemfireTemplate
* @see AbstractUnitAndIntegrationTestsWithMockSupport
* @see org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer
* @see org.springframework.test.context.ContextConfiguration
*/
@RunWith(MockitoJUnitRunner.class)
@SuppressWarnings("unused")
public class GemfireTemplateUnitTests extends AbstractUnitAndIntegrationTestsWithMockSupport {
@Rule
public ExpectedException exception = ExpectedException.none();
private GemfireTemplate template;
@Mock
private Query mockQuery;
@Mock
private QueryService mockQueryService;
@Mock
private Region<?, ?> mockRegion;
@Mock
private RegionService mockRegionService;
@Before
public void setUp() throws Exception {
when(mockRegion.getRegionService()).thenReturn(mockRegionService);
when(mockRegionService.getQueryService()).thenReturn(mockQueryService);
when(mockQueryService.newQuery(anyString())).thenReturn(mockQuery);
template = new GemfireTemplate(mockRegion);
}
@Test
public void constructWithNonNullRegionIsSuccessful() {
GemfireTemplate localTemplate = new GemfireTemplate(mockRegion);
assertThat(localTemplate).isNotNull();
assertThat(localTemplate.getRegion()).isSameAs(mockRegion);
assertThat(localTemplate.isExposeNativeRegion()).isFalse();
}
@Test
public void constructWithNullRegionThrowsIllegalArgumentException() {
exception.expect(IllegalArgumentException.class);
exception.expectCause(is(nullValue(Throwable.class)));
exception.expectMessage("Region is required");
new GemfireTemplate(null);
}
@Test
public void executeWithGemfireCallbackUsesNativeRegion() {
template.setExposeNativeRegion(true);
assertThat(template.isExposeNativeRegion()).isTrue();
assertThat(template.getRegion()).isSameAs(mockRegion);
final AtomicBoolean callbackInvoked = new AtomicBoolean(false);
template.execute(new GemfireCallback<Object>() {
@Override
public Object doInGemfire(Region<?, ?> region) throws GemFireCheckedException, GemFireException {
callbackInvoked.set(true);
assertThat(region).isSameAs(mockRegion);
return null;
}
});
assertThat(callbackInvoked.get()).isTrue();
}
@Test
public void executeWithGemfireCallbackUsesProxyRegion() {
assertThat(template.isExposeNativeRegion()).isFalse();
final AtomicBoolean callbackInvoked = new AtomicBoolean(false);
template.execute(new GemfireCallback<Object>() {
@Override
public Object doInGemfire(Region<?, ?> region) throws GemFireCheckedException, GemFireException {
callbackInvoked.set(true);
assertThat(region).isNotSameAs(mockRegion);
return null;
}
});
assertThat(callbackInvoked.get()).isTrue();
}
@Test
public void queryCallsRegionQuery() throws Exception {
String expectedQuery = "SELECT * FROM /Example";
template.query(expectedQuery);
verify(mockRegion, times(1)).query(eq(expectedQuery));
}
@Test
public void findIsSuccessful() throws Exception {
Object[] expectedParams = { "arg" };
String expectedQuery = "SELECT * FROM /Example";
SelectResults mockSelectResults = mock(SelectResults.class);
when(mockQuery.execute(any(Object[].class))).thenReturn(mockSelectResults);
assertThat(template.find(expectedQuery, expectedParams)).isEqualTo(mockSelectResults);
verify(mockRegion, atLeastOnce()).getRegionService();
verify(mockRegionService, times(1)).getQueryService();
verify(mockQueryService, times(1)).newQuery(eq(expectedQuery));
verify(mockQuery, times(1)).execute(eq(expectedParams));
verifyZeroInteractions(mockSelectResults);
}
@Test(expected = InvalidDataAccessApiUsageException.class)
public void findWithSingleResultQueryThrowsInvalidDataAccessApiUsageException() throws Exception {
Object[] expectedParams = { "arg" };
String expectedQuery = "SELECT 1 FROM /Example";
when(mockQuery.execute(any(Object[].class))).thenReturn(1);
try {
template.find(expectedQuery, expectedParams);
}
finally {
verify(mockRegion, atLeastOnce()).getRegionService();
verify(mockRegionService, times(1)).getQueryService();
verify(mockQueryService, times(1)).newQuery(eq(expectedQuery));
verify(mockQuery, times(1)).execute(eq(expectedParams));
}
}
@Test
public void findUniqueReturnsSelectResultsIsSuccessful() throws Exception {
Object[] expectedParams = { "arg" };
String expectedQuery = "SELECT 1 FROM /Example";
SelectResults mockSelectResults = mock(SelectResults.class);
when(mockQuery.execute(eq(expectedParams))).thenReturn(mockSelectResults);
when(mockSelectResults.asList()).thenReturn(Collections.singletonList(1));
assertThat(template.findUnique(expectedQuery, expectedParams)).isEqualTo(1);
verify(mockRegion, atLeastOnce()).getRegionService();
verify(mockRegionService, times(1)).getQueryService();
verify(mockQueryService, times(1)).newQuery(eq(expectedQuery));
verify(mockQuery, times(1)).execute(eq(expectedParams));
verify(mockSelectResults, times(1)).asList();
}
@Test
public void findUniqueReturnsObjectIsSuccessful() throws Exception {
Object[] expectedParams = { "arg" };
String expectedQuery = "SELECT 1 FROM /Example";
when(mockQuery.execute(eq(expectedParams))).thenReturn("test");
assertThat(template.findUnique(expectedQuery, expectedParams)).isEqualTo("test");
verify(mockRegion, atLeastOnce()).getRegionService();
verify(mockRegionService, times(1)).getQueryService();
verify(mockQueryService, times(1)).newQuery(eq(expectedQuery));
verify(mockQuery, times(1)).execute(eq(expectedParams));
}
@Test(expected = InvalidDataAccessApiUsageException.class)
public void findUniqueWithMultiResultQueryThrowsInvalidDataAccessApiUsageException() throws Exception {
Object[] expectedParams = { "arg" };
String expectedQuery = "SELECT 1 FROM /Example";
SelectResults mockSelectResults = mock(SelectResults.class);
when(mockQuery.execute(eq(expectedParams))).thenReturn(mockSelectResults);
when(mockSelectResults.asList()).thenReturn(Arrays.asList(1, 2));
try {
assertThat(template.findUnique(expectedQuery, expectedParams)).isEqualTo(1);
}
finally {
verify(mockRegion, atLeastOnce()).getRegionService();
verify(mockRegionService, times(1)).getQueryService();
verify(mockQueryService, times(1)).newQuery(eq(expectedQuery));
verify(mockQuery, times(1)).execute(eq(expectedParams));
verify(mockSelectResults, times(1)).asList();
}
}
@Test
@SuppressWarnings("unchecked")
public void resolveClientQueryService() {
ClientCache mockClientCache = mock(ClientCache.class);
Region<Object, Object> mockRegion = mock(Region.class);
RegionAttributes<Object, Object> mockRegionAttributes = mock(RegionAttributes.class);
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
when(mockRegionAttributes.getScope()).thenReturn(Scope.GLOBAL);
when(mockRegion.getRegionService()).thenReturn(mockClientCache);
when(mockClientCache.getQueryService()).thenReturn(mockQueryService);
GemfireTemplate localTemplate = new GemfireTemplate(mockRegion) {
@Override boolean isLocalWithNoServerProxy(Region<?, ?> region) {
return false;
}
};
assertThat(localTemplate.resolveQueryService(mockRegion)).isSameAs(mockQueryService);
verify(mockClientCache, never()).getLocalQueryService();
verify(mockClientCache, times(1)).getQueryService();
verify(mockClientCache, never()).getQueryService(anyString());
verify(mockRegion, times(2)).getAttributes();
verify(mockRegion, times(3)).getRegionService();
verify(mockRegionAttributes, times(1)).getScope();
verifyZeroInteractions(mockQueryService);
}
@Test
@SuppressWarnings("unchecked")
public void resolvesClientLocalQueryService() {
ClientCache mockClientCache = mock(ClientCache.class);
Region<Object, Object> mockRegion = mock(Region.class);
RegionAttributes<Object, Object> mockRegionAttributes = mock(RegionAttributes.class);
when(mockClientCache.getLocalQueryService()).thenReturn(mockQueryService);
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
when(mockRegion.getRegionService()).thenReturn(mockClientCache);
when(mockRegionAttributes.getScope()).thenReturn(Scope.LOCAL);
GemfireTemplate localTemplate = new GemfireTemplate(mockRegion) {
@Override boolean isLocalWithNoServerProxy(Region<?, ?> region) {
return true;
}
};
assertThat(localTemplate.resolveQueryService(mockRegion)).isSameAs(mockQueryService);
verify(mockClientCache, times(1)).getLocalQueryService();
verify(mockClientCache, never()).getQueryService();
verify(mockClientCache, never()).getQueryService(anyString());
verify(mockRegion, times(2)).getRegionService();
verify(mockRegionAttributes, times(1)).getScope();
verifyZeroInteractions(mockQueryService);
}
@Test
@SuppressWarnings("unchecked")
public void resolvesClientPooledQueryService() {
ClientCache mockClientCache = mock(ClientCache.class);
Region<Object, Object> mockRegion = mock(Region.class);
RegionAttributes<Object, Object> mockRegionAttributes = mock(RegionAttributes.class);
when(mockClientCache.getQueryService(anyString())).thenReturn(mockQueryService);
when(mockRegion.getAttributes()).thenReturn(mockRegionAttributes);
when(mockRegion.getRegionService()).thenReturn(mockClientCache);
when(mockRegionAttributes.getPoolName()).thenReturn("TestPool");
when(mockRegionAttributes.getScope()).thenReturn(Scope.LOCAL);
GemfireTemplate localTemplate = new GemfireTemplate(mockRegion) {
@Override boolean isLocalWithNoServerProxy(Region<?, ?> region) {
return false;
}
};
assertThat(localTemplate.resolveQueryService(mockRegion)).isSameAs(mockQueryService);
verify(mockClientCache, never()).getLocalQueryService();
verify(mockClientCache, never()).getQueryService();
verify(mockClientCache, times(1)).getQueryService(eq("TestPool"));
verify(mockRegion, times(2)).getRegionService();
verify(mockRegionAttributes, times(2)).getPoolName();
verify(mockRegionAttributes, times(1)).getScope();
verifyZeroInteractions(mockQueryService);
}
@Test
public void resolvePeerQueryService() {
assertThat(template.resolveQueryService(mockRegion)).isEqualTo(mockQueryService);
verify(mockRegion, times(2)).getRegionService();
verify(mockRegion, never()).getAttributes();
verify(mockRegionService, times(1)).getQueryService();
}
}

View File

@@ -28,10 +28,12 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* The ProcessContext class is a container encapsulating configuration and context meta-data for a running process.
* The {@link ProcessConfiguration} class is a container encapsulating configuration and context meta-data
* for a running process.
*
* @author John Blum
* @see java.lang.ProcessBuilder
* @see org.springframework.data.gemfire.process.ProcessExecutor
* @since 1.5.0
*/
@SuppressWarnings("unused")
@@ -46,23 +48,23 @@ public class ProcessConfiguration {
private final Map<String, String> environment;
public static ProcessConfiguration create(ProcessBuilder processBuilder) {
Assert.notNull(processBuilder, "The ProcessBuilder used to configure and start the Process must not be null!");
Assert.notNull(processBuilder, "The ProcessBuilder used to configure and start the Process must not be null");
return new ProcessConfiguration(processBuilder.command(), processBuilder.directory(),
processBuilder.environment(), processBuilder.redirectErrorStream());
}
public ProcessConfiguration(List<String> command, File workingDirectory, Map<String, String> environment,
boolean redirectingErrorStream) {
boolean redirectErrorStream) {
Assert.notEmpty(command, "process command must be specified");
Assert.notEmpty(command, "Process command must be specified");
Assert.isTrue(FileSystemUtils.isDirectory(workingDirectory), String.format(
"process working directory [%1$s] is not valid", workingDirectory));
"Process working directory [%s] is not valid", workingDirectory));
this.command = new ArrayList<String>(command);
this.workingDirectory = workingDirectory;
this.redirectingErrorStream = redirectingErrorStream;
this.redirectingErrorStream = redirectErrorStream;
this.environment = (environment != null
? Collections.unmodifiableMap(new HashMap<String, String>(environment))
@@ -93,9 +95,8 @@ public class ProcessConfiguration {
public String toString() {
return "{ command = ".concat(getCommandString())
.concat(", workingDirectory = ".concat(getWorkingDirectory().getAbsolutePath()))
.concat(", redirectingErrorStream = ".concat(String.valueOf(isRedirectingErrorStream())))
.concat(", environment = ".concat(String.valueOf(getEnvironment())))
.concat(", redirectingErrorStream = ".concat(String.valueOf(isRedirectingErrorStream())))
.concat(" }");
}
}

View File

@@ -28,11 +28,12 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* The ProcessExecutor class is a utility class for launching and running Java processes.
* The {@link ProcessExecutor} class is a utility class for launching and running Java processes.
*
* @author John Blum
* @see java.lang.Process
* @see java.lang.ProcessBuilder
* @see java.lang.System
* @see org.springframework.data.gemfire.process.ProcessConfiguration
* @see org.springframework.data.gemfire.process.ProcessWrapper
* @since 1.5.0
@@ -68,7 +69,7 @@ public abstract class ProcessExecutor {
processWrapper.register(new ProcessInputStreamListener() {
@Override public void onInput(final String input) {
System.err.printf("[FORK-OUT] - %1$s%n", input);
System.err.printf("[FORK-OUT] - %s%n", input);
}
});
@@ -76,7 +77,7 @@ public abstract class ProcessExecutor {
}
protected static String[] buildCommand(String classpath, Class<?> type, String... args) {
Assert.notNull(type, "The main Java class to launch must not be null!");
Assert.notNull(type, "The main Java class to launch must not be null");
List<String> command = new ArrayList<String>();
List<String> programArgs = Collections.emptyList();
@@ -125,7 +126,8 @@ public abstract class ProcessExecutor {
protected static File validateDirectory(File workingDirectory) {
Assert.isTrue(workingDirectory != null && (workingDirectory.isDirectory() || workingDirectory.mkdirs()),
String.format("Failed to create working directory [%1$s]", workingDirectory));
String.format("Failed to create working directory [%s]", workingDirectory));
return workingDirectory;
}
}

View File

@@ -19,8 +19,8 @@ package org.springframework.data.gemfire.process;
import java.util.EventListener;
/**
* The ProcessStreamListener interface is a callback listener that gets called when input arrives from either a
* process's standard output steam or standard error stream.
* The {@link ProcessInputStreamListener} is a callback interface that gets called when input arrives from either a
* {@link Process process's} standard output steam or standard error stream.
*
* @author John Blum
* @see java.util.EventListener
@@ -28,6 +28,14 @@ import java.util.EventListener;
*/
public interface ProcessInputStreamListener extends EventListener {
/**
* Callback method that gets called when the {@link Process} sends output from either its standard out
* or standard error streams.
*
* @param input {@link String} containing output from the {@link Process} that this listener is listening to.
* @see java.lang.Process#getErrorStream()
* @see java.lang.Process#getInputStream()
*/
void onInput(String input);
}

View File

@@ -73,7 +73,7 @@ public class ProcessWrapper {
Assert.notNull(process, "Process must not be null");
Assert.notNull(processConfiguration, "The context and configuration meta-data providing details about"
+ " the environment in which the process is running and how the process was configured must not be null!");
+ " the environment in which the process is running and how the process was configured must not be null");
this.process = process;
this.processConfiguration = processConfiguration;
@@ -103,8 +103,8 @@ public class ProcessWrapper {
}
}
catch (IOException ignore) {
// ignore IO error and just stop reading from the process input stream
// IO error occurred most likely because the process was terminated
// Ignore IO error and just stop reading from the process input stream
// An IO error occurred most likely because the process was terminated
}
finally {
IOUtils.close(inputReader);
@@ -115,11 +115,14 @@ public class ProcessWrapper {
}
protected Thread newThread(String name, Runnable task) {
Assert.isTrue(!StringUtils.isEmpty(name), "Thread name must be specified");
Assert.hasText(name, "Thread name must be specified");
Assert.notNull(task, "Thread task must not be null");
Thread thread = new Thread(task, name);
thread.setDaemon(DEFAULT_DAEMON_THREAD);
thread.setPriority(Thread.NORM_PRIORITY);
return thread;
}
@@ -175,7 +178,7 @@ public class ProcessWrapper {
public String readLogFile() throws IOException {
File[] logFiles = FileSystemUtils.listFiles(getWorkingDirectory(), new FileFilter() {
@Override public boolean accept(final File pathname) {
@Override public boolean accept(File pathname) {
return (pathname != null && (pathname.isDirectory() || pathname.getAbsolutePath().endsWith(".log")));
}
});
@@ -185,11 +188,11 @@ public class ProcessWrapper {
}
else {
throw new FileNotFoundException(String.format(
"No log files were found in the process's working directory (%1$s)!", getWorkingDirectory()));
"No log files found in process's working directory [%s]", getWorkingDirectory()));
}
}
public String readLogFile(final File log) throws IOException {
public String readLogFile(File log) throws IOException {
return FileUtils.read(log);
}
@@ -210,7 +213,7 @@ public class ProcessWrapper {
ProcessUtils.signalStop(process);
}
catch (IOException e) {
log.warning("Failed to signal the process to stop!");
log.warning("Failed to signal the process to stop");
if (log.isLoggable(Level.FINE)) {
log.fine(ThrowableUtils.toString(e));
@@ -245,7 +248,7 @@ public class ProcessWrapper {
while (!exited.get() && System.currentTimeMillis() < timeout) {
try {
exitValue = futureExitValue.get(milliseconds, TimeUnit.MILLISECONDS);
log.info(String.format("Process [%1$s] has stopped.%n", pid));
log.info(String.format("Process [%s] has stopped%n", pid));
}
catch (InterruptedException ignore) {
interrupted = true;
@@ -254,7 +257,7 @@ public class ProcessWrapper {
}
catch (TimeoutException e) {
exitValue = -1;
log.warning(String.format("Process [%1$d] did not stop within the allotted timeout of %2$d seconds.%n",
log.warning(String.format("Process [%1$d] did not stop within the allotted timeout of %2$d seconds%n",
pid, TimeUnit.MILLISECONDS.toSeconds(milliseconds)));
}
catch (Exception ignore) {
@@ -277,7 +280,7 @@ public class ProcessWrapper {
public int shutdown() {
if (isRunning()) {
log.info(String.format("Stopping process [%1$d]...%n", safeGetPid()));
log.info(String.format("Stopping process [%d]...%n", safeGetPid()));
signalStop();
waitFor();
}
@@ -300,5 +303,4 @@ public class ProcessWrapper {
}
});
}
}

View File

@@ -37,8 +37,7 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* The ProcessUtils class is a utility class for working with process, or specifically instances
* of the Java Process class.
* The {@link ProcessUtils} class is a utility class for working with Operating System (OS) {@link Process processes}.
*
* @author John Blum
* @see java.io.File
@@ -74,8 +73,8 @@ public abstract class ProcessUtils {
}
}
throw new PidUnavailableException(String.format("process ID (PID) not available [%1$s]",
runtimeMXBeanName), cause);
throw new PidUnavailableException(String.format("Process ID (PID) not available [%s]", runtimeMXBeanName),
cause);
}
public static boolean isRunning(int processId) {
@@ -120,7 +119,7 @@ public abstract class ProcessUtils {
if (pidFile == null) {
throw new PidUnavailableException(String.format(
"no PID file was found in working directory [%1$s] or any of it's sub-directories",
"No PID file was found in working directory [%s] or any of it's sub-directories",
workingDirectory));
}
@@ -130,7 +129,7 @@ public abstract class ProcessUtils {
@SuppressWarnings("all")
protected static File findPidFile(File workingDirectory) {
Assert.isTrue(FileSystemUtils.isDirectory(workingDirectory), String.format(
"File [%1$s] is not a valid directory", workingDirectory));
"File [%s] is not a valid directory", workingDirectory));
for (File file : workingDirectory.listFiles(DirectoryPidFileFilter.INSTANCE)) {
if (file.isDirectory()) {
@@ -148,7 +147,7 @@ public abstract class ProcessUtils {
@SuppressWarnings("all")
public static int readPid(File pidFile) {
Assert.isTrue(pidFile != null && pidFile.isFile(), String.format(
"File [%1$s] is not a valid file", pidFile));
"File [%s] is not a valid file", pidFile));
BufferedReader fileReader = null;
String pidValue = null;
@@ -156,6 +155,7 @@ public abstract class ProcessUtils {
try {
fileReader = new BufferedReader(new FileReader(pidFile));
pidValue = String.valueOf(fileReader.readLine()).trim();
return Integer.parseInt(pidValue);
}
catch (FileNotFoundException e) {
@@ -176,9 +176,9 @@ public abstract class ProcessUtils {
@SuppressWarnings("all")
public static void writePid(File pidFile, int pid) throws IOException {
Assert.isTrue(pidFile != null && (pidFile.isFile() || pidFile.createNewFile()), String.format(
"File [%1$s] is not a valid file", pidFile));
"File [%s] is not a valid file", pidFile));
Assert.isTrue(pid > 0, String.format("PID [%1$d] must greater than 0", pid));
Assert.isTrue(pid > 0, String.format("PID [%d] must greater than 0", pid));
PrintWriter fileWriter = new PrintWriter(new BufferedWriter(new FileWriter(pidFile, false), 16), true);
@@ -210,5 +210,4 @@ public abstract class ProcessUtils {
return (path != null && path.isFile() && path.getName().toLowerCase().endsWith(".pid"));
}
}
}

View File

@@ -1,162 +0,0 @@
/*
* Copyright 2012 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.data.gemfire.repository.support;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Collection;
import javax.annotation.Resource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.gemfire.GemfireTemplate;
import org.springframework.data.gemfire.repository.sample.Person;
import org.springframework.data.repository.core.EntityInformation;
import org.springframework.data.repository.core.support.ReflectionEntityInformation;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionEvent;
import com.gemstone.gemfire.cache.query.SelectResults;
import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
/**
* Integration tests for {@link SimpleGemfireRepository}.
*
* @author Oliver Gierke
* @author John Blum
* @see org.junit.Test
* @see org.springframework.data.gemfire.repository.support.SimpleGemfireRepository
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("../../basic-template.xml")
public class SimpleGemfireRepositoryIntegrationTest {
@Autowired
GemfireTemplate template;
@Resource(name = "simple")
Region<?, ?> simpleRegion;
SimpleGemfireRepository<Person, Long> repository;
RegionClearListener regionClearListener;
@Before
@SuppressWarnings("unchecked")
public void setUp() {
simpleRegion.clear();
regionClearListener = new RegionClearListener();
simpleRegion.getAttributesMutator().addCacheListener(regionClearListener);
EntityInformation<Person, Long> information = new ReflectionEntityInformation<Person, Long>(Person.class);
repository = new SimpleGemfireRepository<Person, Long>(template, information);
}
@Test
public void storeAndDeleteEntity() {
Person person = new Person(1L, "Oliver", "Gierke");
repository.save(person);
assertThat(repository.count(), is(1L));
assertThat(repository.findOne(person.id), is(person));
assertThat(repository.findAll().size(), is(1));
repository.delete(person);
assertThat(repository.count(), is(0L));
assertThat(repository.findOne(person.id), is(nullValue()));
assertThat(repository.findAll().size(), is(0));
}
@Test
public void testDeleteAllFiresClearEvent() {
assertFalse(regionClearListener.eventFired);
repository.deleteAll();
assertTrue(regionClearListener.eventFired);
}
@Test
public void queryRegion() throws Exception {
Person person = new Person(1L, "Oliver", "Gierke");
template.put(1L, person);
SelectResults<Person> persons = template.find("SELECT * FROM /simple s WHERE s.firstname = $1",
person.firstname);
assertThat(persons.size(), is(1));
assertThat(persons.iterator().next(), is(person));
}
@Test
public void findAllWithGivenIds() {
Person dave = new Person(1L, "Dave", "Matthews");
Person carter = new Person(2L, "Carter", "Beauford");
Person leroi = new Person(3L, "Leroi", "Moore");
template.put(dave.id, dave);
template.put(carter.id, carter);
template.put(leroi.id, leroi);
Collection<Person> result = repository.findAll(Arrays.asList(carter.id, leroi.id));
assertThat(result, hasItems(carter, leroi));
assertThat(result, not(hasItems(dave)));
}
@Test
public void testSaveEntities() {
assertTrue(template.getRegion().isEmpty());
Person johnBlum = new Person(1l, "John", "Blum");
Person jonBloom = new Person(2l, "Jon", "Bloom");
Person juanBlume = new Person(3l, "Juan", "Blume");
repository.save(Arrays.asList(johnBlum, jonBloom, juanBlume));
assertFalse(template.getRegion().isEmpty());
assertEquals(3, template.getRegion().size());
assertEquals(johnBlum, template.get(johnBlum.id));
assertEquals(jonBloom, template.get(jonBloom.id));
assertEquals(juanBlume, template.get(juanBlume.id));
}
@SuppressWarnings("rawtypes")
public static class RegionClearListener extends CacheListenerAdapter {
public boolean eventFired;
@Override
public void afterRegionClear(RegionEvent ev) {
eventFired = true;
}
}
}

View File

@@ -0,0 +1,209 @@
/*
* Copyright 2012 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.data.gemfire.repository.support;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Properties;
import javax.annotation.Resource;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionEvent;
import com.gemstone.gemfire.cache.query.SelectResults;
import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.GemfireTemplate;
import org.springframework.data.gemfire.LocalRegionFactoryBean;
import org.springframework.data.gemfire.repository.sample.Person;
import org.springframework.data.repository.core.EntityInformation;
import org.springframework.data.repository.core.support.ReflectionEntityInformation;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Integration tests for {@link SimpleGemfireRepository}.
*
* @author Oliver Gierke
* @author John Blum
* @see org.junit.Test
* @see org.springframework.data.gemfire.repository.support.SimpleGemfireRepository
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@SuppressWarnings("unused")
public class SimpleGemfireRepositoryIntegrationTests {
protected static final String DEFAULT_GEMFIRE_LOG_LEVEL = "warning";
@Autowired
private GemfireTemplate template;
@Resource(name = "People")
private Region<?, ?> people;
private RegionClearListener regionClearListener;
private SimpleGemfireRepository<Person, Long> repository;
@Before
@SuppressWarnings("unchecked")
public void setUp() {
people.clear();
regionClearListener = new RegionClearListener();
people.getAttributesMutator().addCacheListener(regionClearListener);
EntityInformation<Person, Long> information = new ReflectionEntityInformation<Person, Long>(Person.class);
repository = new SimpleGemfireRepository<Person, Long>(template, information);
}
@Test
public void saveAndDeleteEntity() {
Person oliverGierke = new Person(1L, "Oliver", "Gierke");
assertThat(repository.save(oliverGierke)).isEqualTo(oliverGierke);
assertThat(repository.count()).isEqualTo(1L);
assertThat(repository.findOne(oliverGierke.getId())).isEqualTo(oliverGierke);
assertThat(repository.findAll()).isEqualTo(Collections.singletonList(oliverGierke));
repository.delete(oliverGierke);
assertThat(repository.count()).isEqualTo(0L);
assertThat(repository.findOne(oliverGierke.getId())).isNull();
assertThat(repository.findAll()).isEmpty();
}
@Test
public void deleteAllFiresClearEvent() {
assertThat(regionClearListener.eventFired).isFalse();
repository.deleteAll();
assertThat(regionClearListener.eventFired).isTrue();
}
@Test
public void queryRegion() throws Exception {
Person oliverGierke = new Person(1L, "Oliver", "Gierke");
assertThat(template.put(oliverGierke.getId(), oliverGierke)).isNull();
SelectResults<Person> people = template.find("SELECT * FROM /People p WHERE p.firstname = $1",
oliverGierke.getFirstname());
assertThat(people.size()).isEqualTo(1);
assertThat(people.iterator().next()).isEqualTo(oliverGierke);
}
@Test
public void findAllWithGivenIds() {
Person dave = new Person(1L, "Dave", "Matthews");
Person carter = new Person(2L, "Carter", "Beauford");
Person leroi = new Person(3L, "Leroi", "Moore");
template.put(dave.getId(), dave);
template.put(carter.getId(), carter);
template.put(leroi.getId(), leroi);
Collection<Person> result = repository.findAll(Arrays.asList(carter.getId(), leroi.getId()));
assertThat(result).isNotNull();
assertThat(result.size()).isEqualTo(2);
assertThat(result).containsAll(Arrays.asList(carter, leroi));
}
@Test
public void saveEntities() {
assertThat(template.getRegion()).isEmpty();
Person johnBlum = new Person(1l, "John", "Blum");
Person jonBloom = new Person(2l, "Jon", "Bloom");
Person juanBlume = new Person(3l, "Juan", "Blume");
repository.save(Arrays.asList(johnBlum, jonBloom, juanBlume));
assertThat(template.getRegion().size()).isEqualTo(3);
assertThat(template.get(johnBlum.getId())).isEqualTo(johnBlum);
assertThat(template.get(jonBloom.getId())).isEqualTo(jonBloom);
assertThat(template.get(juanBlume.getId())).isEqualTo(juanBlume);
}
@SuppressWarnings("rawtypes")
public static class RegionClearListener extends CacheListenerAdapter {
public volatile boolean eventFired;
@Override
public void afterRegionClear(RegionEvent ev) {
eventFired = true;
}
}
@Configuration
static class SimpleGemfireRepositoryConfiguration {
Properties gemfireProperties() {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", applicationName());
gemfireProperties.setProperty("mcast-port", "0");
gemfireProperties.setProperty("log-level", logLevel());
return gemfireProperties;
}
String applicationName() {
return SimpleGemfireRepositoryIntegrationTests.class.getName();
}
String logLevel() {
return System.getProperty("gemfire.log-level", DEFAULT_GEMFIRE_LOG_LEVEL);
}
@Bean
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(false);
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
@Bean(name = "People")
LocalRegionFactoryBean<Object, Object> peopleRegion(GemFireCache gemfireCache) {
LocalRegionFactoryBean<Object, Object> peopleRegion = new LocalRegionFactoryBean<Object, Object>();
peopleRegion.setCache(gemfireCache);
peopleRegion.setClose(false);
peopleRegion.setPersistent(false);
return peopleRegion;
}
@Bean
GemfireTemplate peopleRegionTemplate(Region<Object, Object> people) {
return new GemfireTemplate(people);
}
}
}

View File

@@ -39,6 +39,7 @@ import org.springframework.util.Assert;
* @see org.springframework.data.gemfire.process.ProcessWrapper
* @since 1.8.0
*/
@Deprecated
@SuppressWarnings("unused")
public abstract class AbstractGemFireClientServerIntegrationTest {

View File

@@ -14,39 +14,45 @@
* limitations under the License.
*/
package org.springframework.data.gemfire.test;
package org.springframework.data.gemfire.test.support;
import org.springframework.data.gemfire.test.support.IdentifierSequence;
import org.springframework.data.gemfire.test.support.StackTraceUtils;
import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer;
import org.springframework.util.StringUtils;
/**
* The AbstractMockery class is an abstract base class supporting the creation and use of mock objects in unit tests.
* {@link AbstractUnitAndIntegrationTestsWithMockSupport} is an abstract base class for test classes
* having support for the creation and use of mock objects in test cases, but that may also be ran
* as integration tests using actual GemFire components (e.g. Regions, etc).
*
* @author John Blum
* @see org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer
* @since 1.5.3
*/
@SuppressWarnings("unused")
public abstract class AbstractMockerySupport {
public abstract class AbstractUnitAndIntegrationTestsWithMockSupport {
protected static final String GEMFIRE_TEST_RUNNER_NO_MOCK =
System.getProperty(GemfireTestApplicationContextInitializer.GEMFIRE_TEST_RUNNER_DISABLED, "false");
protected static final String NOT_IMPLEMENTED = "Not Implemented";
/* (non-Javadoc) */
protected boolean isMocking() {
String gemfireTestRunnerNoMock = StringUtils.trimWhitespace(System.getProperty(
GemfireTestApplicationContextInitializer.GEMFIRE_TEST_RUNNER_DISABLED, "false"));
String gemfireTestRunnerNoMock = StringUtils.trimWhitespace(GEMFIRE_TEST_RUNNER_NO_MOCK);
return !(Boolean.parseBoolean(gemfireTestRunnerNoMock)
|| "yes".equalsIgnoreCase(gemfireTestRunnerNoMock)
|| "y".equalsIgnoreCase(gemfireTestRunnerNoMock));
}
/* (non-Javadoc) */
protected boolean isNotMocking() {
return !isMocking();
}
/* (non-Javadoc) */
protected Object getMockId() {
StackTraceElement element = StackTraceUtils.getTestCaller();
return (element != null ? StackTraceUtils.getCallerSimpleName(element): IdentifierSequence.nextId());
return (element != null ? StackTraceUtils.getCallerSimpleName(element) : IdentifierSequence.nextId());
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright 2016 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.data.gemfire.test.support;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import com.gemstone.gemfire.cache.server.CacheServer;
/**
* The {@link ClientServerIntegrationTestsSupport} class is a abstract base class encapsulating common functionality
* to support the implementation of GemFire client/server tests.
*
* @author John Blum
* @see com.gemstone.gemfire.cache.server.CacheServer
* @see org.springframework.data.gemfire.test.support.SocketUtils
* @see org.springframework.data.gemfire.test.support.ThreadUtils
* @since 1.9.0
*/
@SuppressWarnings("unused")
public class ClientServerIntegrationTestsSupport {
protected static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(20);
protected static final long DEFAULT_WAIT_INTERVAL = 500L;
/* (non-Javadoc) */
protected static File createDirectory(String pathname) {
File directory = new File(pathname);
assertThat(directory.isDirectory() || directory.mkdirs())
.as(String.format("Failed to create directory [%s]", directory)).isTrue();
directory.deleteOnExit();
return directory;
}
/* (non-Javadoc) */
protected static boolean waitForCacheServerToStart(CacheServer cacheServer) {
return waitForCacheServerToStart(cacheServer.getBindAddress(), cacheServer.getPort(), DEFAULT_WAIT_DURATION);
}
/* (non-Javadoc) */
protected static boolean waitForCacheServerToStart(CacheServer cacheServer, long duration) {
return waitForCacheServerToStart(cacheServer.getBindAddress(), cacheServer.getPort(), duration);
}
/* (non-Javadoc) */
protected static boolean waitForCacheServerToStart(String host, int port) {
return waitForCacheServerToStart(host, port, DEFAULT_WAIT_DURATION);
}
/* (non-Javadoc) */
protected static boolean waitForCacheServerToStart(final String host, final int port, long duration) {
return ThreadUtils.timedWait(duration, DEFAULT_WAIT_INTERVAL, new ThreadUtils.WaitCondition() {
AtomicBoolean connected = new AtomicBoolean(false);
public boolean waiting() {
Socket socket = null;
try {
if (!connected.get()) {
socket = new Socket(host, port);
connected.set(true);
}
}
catch (IOException ignore) {
}
finally {
SocketUtils.close(socket);
}
return !connected.get();
}
});
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2016 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.data.gemfire.test.support;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Logger;
/**
* {@link SocketUtils} is a utility class for managing {@link Socket} and {@link ServerSocket} objects.
*
* @author John Blum
* @see java.net.ServerSocket
* @see java.net.Socket
* @since 1.9.0
*/
@SuppressWarnings("unused")
public abstract class SocketUtils {
private static final Logger log = Logger.getLogger(SocketUtils.class.getName());
/* (non-Javadoc) */
public static boolean close(Socket socket) {
try {
if (socket != null) {
socket.close();
return true;
}
}
catch (IOException ignore) {
log.warning(String.format("Failed to close Socket [%s]", socket));
log.warning(ThrowableUtils.toString(ignore));
}
return false;
}
/* (non-Javadoc) */
public static boolean close(ServerSocket serverSocket) {
try {
if (serverSocket != null) {
serverSocket.close();
return true;
}
}
catch (IOException ignore) {
log.warning(String.format("Failed to close ServerSocket [%s]", serverSocket));
log.warning(ThrowableUtils.toString(ignore));
}
return false;
}
}

View File

@@ -19,7 +19,7 @@ package org.springframework.data.gemfire.test.support;
import java.util.concurrent.TimeUnit;
/**
* The ThreadUtils class is a utility class for working with Java Threads.
* {@link ThreadUtils} is an abstract utility class for managing Java {@link Thread Threads}.
*
* @author John Blum
* @see java.lang.Thread
@@ -28,46 +28,52 @@ import java.util.concurrent.TimeUnit;
@SuppressWarnings("unused")
public abstract class ThreadUtils {
public static boolean sleep(final long milliseconds) {
/* (non-Javadoc) */
public static boolean sleep(long milliseconds) {
try {
Thread.sleep(milliseconds);
return true;
}
catch (InterruptedException ignore) {
Thread.currentThread().interrupt();
return false;
}
}
public static void timedWait(final long duration) {
timedWait(duration, duration);
public static boolean timedWait(long duration) {
return timedWait(duration, duration);
}
public static void timedWait(final long duration, final long interval) {
timedWait(duration, interval, new WaitCondition() {
public static boolean timedWait(long duration, long interval) {
return timedWait(duration, interval, new WaitCondition() {
@Override public boolean waiting() {
return true;
}
});
}
public static void timedWait(final long duration, long interval, final WaitCondition waitCondition) {
@SuppressWarnings("all")
public static boolean timedWait(long duration, long interval, WaitCondition waitCondition) {
final long timeout = (System.currentTimeMillis() + duration);
interval = Math.min(interval, duration);
while (waitCondition.waiting() && (System.currentTimeMillis() < timeout)) {
try {
try {
while (waitCondition.waiting() && (System.currentTimeMillis() < timeout)) {
synchronized (waitCondition) {
TimeUnit.MILLISECONDS.timedWait(waitCondition, interval);
}
}
catch (InterruptedException ignore) {
}
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return !waitCondition.waiting();
}
public static interface WaitCondition {
// TODO rename interface to Condition and waiting() method to evaluate()
public interface WaitCondition {
boolean waiting();
}
}