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:
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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(" }");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user