Java tutorial
/* * Copyright (C) 2012-2014 DuyHai DOAN * * 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 info.archinnov.achilles.test.integration.tests; import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; import static com.datastax.driver.core.querybuilder.QueryBuilder.set; import static com.datastax.driver.core.querybuilder.QueryBuilder.update; import static info.archinnov.achilles.listener.LWTResultListener.LWTResult.Operation.INSERT; import static info.archinnov.achilles.listener.LWTResultListener.LWTResult.Operation.UPDATE; import static info.archinnov.achilles.test.integration.entity.CompleteBeanTestBuilder.builder; import static info.archinnov.achilles.type.ConsistencyLevel.EACH_QUORUM; import static info.archinnov.achilles.type.ConsistencyLevel.LOCAL_SERIAL; import static info.archinnov.achilles.type.ConsistencyLevel.ONE; import static info.archinnov.achilles.type.OptionsBuilder.*; import static org.fest.assertions.api.Assertions.assertThat; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import info.archinnov.achilles.exception.AchillesLightWeightTransactionException; import info.archinnov.achilles.junit.AchillesTestResource.Steps; import info.archinnov.achilles.listener.LWTResultListener; import org.apache.commons.lang3.RandomUtils; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import com.datastax.driver.core.RegularStatement; import com.google.common.collect.ImmutableMap; import info.archinnov.achilles.persistence.PersistenceManager; import info.archinnov.achilles.query.cql.NativeQuery; import info.archinnov.achilles.test.integration.AchillesInternalCQLResource; import info.archinnov.achilles.test.integration.entity.CompleteBean; import info.archinnov.achilles.test.integration.entity.EntityWithEnum; import info.archinnov.achilles.test.integration.utils.CassandraLogAsserter; import info.archinnov.achilles.type.OptionsBuilder; public class LWTOperationsIT { @Rule public AchillesInternalCQLResource resource = new AchillesInternalCQLResource(Steps.BOTH, EntityWithEnum.TABLE_NAME, CompleteBean.TABLE_NAME); private PersistenceManager manager = resource.getPersistenceManager(); private CassandraLogAsserter logAsserter = new CassandraLogAsserter(); @Test public void should_insert_when_not_exists() throws Exception { //Given final EntityWithEnum entityWithEnum = new EntityWithEnum(10L, "name", EACH_QUORUM); //When logAsserter.prepareLogLevelForDriverConnection(); manager.insert(entityWithEnum, OptionsBuilder.ifNotExists().lwtLocalSerial()); final EntityWithEnum found = manager.find(EntityWithEnum.class, 10L); //Then assertThat(found).isNotNull(); assertThat(found.getName()).isEqualTo("name"); assertThat(found.getConsistencyLevel()).isEqualTo(EACH_QUORUM); logAsserter.assertSerialConsistencyLevels(LOCAL_SERIAL, ONE); } @Test public void should_insert_and_notify_LWT_listener_on_success() throws Exception { final AtomicBoolean LWTSuccess = new AtomicBoolean(false); LWTResultListener listener = new LWTResultListener() { @Override public void onSuccess() { LWTSuccess.compareAndSet(false, true); } @Override public void onError(LWTResult lwtResult) { } }; //Given final EntityWithEnum entityWithEnum = new EntityWithEnum(10L, "name", EACH_QUORUM); //When manager.insertOrUpdate(entityWithEnum, OptionsBuilder.ifNotExists().lwtResultListener(listener)); final EntityWithEnum found = manager.find(EntityWithEnum.class, 10L); //Then assertThat(found).isNotNull(); assertThat(found.getName()).isEqualTo("name"); assertThat(found.getConsistencyLevel()).isEqualTo(EACH_QUORUM); assertThat(LWTSuccess.get()).isTrue(); } @Test public void should_exception_when_trying_to_insert_with_LWT_because_already_exist() throws Exception { //Given final EntityWithEnum entityWithEnum = new EntityWithEnum(10L, "name", EACH_QUORUM); Map<String, Object> expectedCurrentValues = ImmutableMap.<String, Object>of("id", 10L, "[applied]", false, "consistency_level", EACH_QUORUM.name(), "name", "name"); AchillesLightWeightTransactionException lwtException = null; manager.insert(entityWithEnum); //When try { manager.insert(entityWithEnum, OptionsBuilder.ifNotExists()); } catch (AchillesLightWeightTransactionException ace) { lwtException = ace; } assertThat(lwtException).isNotNull(); assertThat(lwtException.operation()).isEqualTo(INSERT); assertThat(lwtException.currentValues()).isEqualTo(expectedCurrentValues); assertThat(lwtException.toString()).isEqualTo( "CAS operation INSERT cannot be applied. Current values are: {[applied]=false, consistency_level=EACH_QUORUM, id=10, name=name}"); } @Test public void should_notify_listener_when_trying_to_insert_with_LWT_because_already_exist() throws Exception { //Given final AtomicReference<LWTResultListener.LWTResult> atomicLWTResult = new AtomicReference(null); LWTResultListener listener = new LWTResultListener() { @Override public void onSuccess() { } @Override public void onError(LWTResult lwtResult) { atomicLWTResult.compareAndSet(null, lwtResult); } }; final EntityWithEnum entityWithEnum = new EntityWithEnum(10L, "name", EACH_QUORUM); Map<String, Object> expectedCurrentValues = ImmutableMap.<String, Object>of("id", 10L, "[applied]", false, "consistency_level", EACH_QUORUM.name(), "name", "name"); manager.insert(entityWithEnum); manager.insert(entityWithEnum, OptionsBuilder.ifNotExists().lwtResultListener(listener)); final LWTResultListener.LWTResult lwtResult = atomicLWTResult.get(); assertThat(lwtResult.operation()).isEqualTo(INSERT); assertThat(lwtResult.currentValues()).isEqualTo(expectedCurrentValues); assertThat(lwtResult.toString()).isEqualTo( "CAS operation INSERT cannot be applied. Current values are: {[applied]=false, consistency_level=EACH_QUORUM, id=10, name=name}"); } @Test public void should_notify_listener_when_trying_to_insert_with_lwt_and_ttl_because_already_exist() throws Exception { //Given final AtomicReference<LWTResultListener.LWTResult> atomicLWTResult = new AtomicReference(null); LWTResultListener listener = new LWTResultListener() { @Override public void onSuccess() { } @Override public void onError(LWTResult lwtResult) { atomicLWTResult.compareAndSet(null, lwtResult); } }; final EntityWithEnum entityWithEnum = new EntityWithEnum(10L, "name", EACH_QUORUM); Map<String, Object> expectedCurrentValues = ImmutableMap.<String, Object>of("id", 10L, "[applied]", false, "consistency_level", EACH_QUORUM.name(), "name", "name"); manager.insert(entityWithEnum); manager.insert(entityWithEnum, OptionsBuilder.ifNotExists().withTtl(100).lwtResultListener(listener)); final LWTResultListener.LWTResult LWTResult = atomicLWTResult.get(); assertThat(LWTResult.operation()).isEqualTo(INSERT); assertThat(LWTResult.currentValues()).isEqualTo(expectedCurrentValues); assertThat(LWTResult.toString()).isEqualTo( "CAS operation INSERT cannot be applied. Current values are: {[applied]=false, consistency_level=EACH_QUORUM, id=10, name=name}"); } @Test public void should_update_with_cas_conditions_using_enum() throws Exception { //Given final EntityWithEnum entityWithEnum = new EntityWithEnum(10L, "John", EACH_QUORUM); final EntityWithEnum managed = manager.insert(entityWithEnum); managed.setName("Helen"); //When manager.insertOrUpdate(managed, ifEqualCondition("name", "John").ifEqualCondition("consistency_level", EACH_QUORUM)); //Then final EntityWithEnum found = manager.find(EntityWithEnum.class, 10L); assertThat(found).isNotNull(); assertThat(found.getName()).isEqualTo("Helen"); assertThat(found.getConsistencyLevel()).isEqualTo(EACH_QUORUM); } @Test public void should_update_with_cas_conditions_using_cql_column_name() throws Exception { //Given final Long primaryKey = RandomUtils.nextLong(0, Long.MAX_VALUE); final CompleteBean entity = new CompleteBean(); entity.setId(primaryKey); entity.setAge(32L); entity.setName("John"); List<String> friends = new ArrayList<>(); friends.add("Paul"); entity.setFriends(friends); final CompleteBean managed = manager.insert(entity); managed.setName("Helen"); managed.getFriends().add("George"); //When manager.update(managed, ifEqualCondition("age_in_years", 32L)); //Then final CompleteBean found = manager.find(CompleteBean.class, primaryKey); assertThat(found).isNotNull(); assertThat(found.getName()).isEqualTo("Helen"); } @Test public void should_exception_when_failing_cas_update() throws Exception { //Given final EntityWithEnum entityWithEnum = new EntityWithEnum(10L, "John", EACH_QUORUM); final EntityWithEnum managed = manager.insert(entityWithEnum); Map<String, Object> expectedCurrentValues = ImmutableMap.<String, Object>of("[applied]", false, "consistency_level", EACH_QUORUM.name(), "name", "John"); AchillesLightWeightTransactionException lwtException = null; managed.setName("Helen"); //When try { manager.update(managed, ifEqualCondition("name", "name").ifEqualCondition("consistency_level", EACH_QUORUM)); } catch (AchillesLightWeightTransactionException ace) { lwtException = ace; } assertThat(lwtException).isNotNull(); assertThat(lwtException.operation()).isEqualTo(UPDATE); assertThat(lwtException.currentValues()).isEqualTo(expectedCurrentValues); assertThat(lwtException.toString()).isEqualTo( "CAS operation UPDATE cannot be applied. Current values are: {[applied]=false, consistency_level=EACH_QUORUM, name=John}"); } @Test public void should_notify_listener_when_failing_cas_update() throws Exception { //Given final AtomicReference<LWTResultListener.LWTResult> atomicCASResult = new AtomicReference(null); LWTResultListener listener = new LWTResultListener() { @Override public void onSuccess() { } @Override public void onError(LWTResult lwtResult) { atomicCASResult.compareAndSet(null, lwtResult); } }; final EntityWithEnum entityWithEnum = new EntityWithEnum(10L, "John", EACH_QUORUM); final EntityWithEnum managed = manager.insert(entityWithEnum); Map<String, Object> expectedCurrentValues = ImmutableMap.<String, Object>of("[applied]", false, "consistency_level", EACH_QUORUM.name(), "name", "John"); managed.setName("Helen"); //When manager.update(managed, ifEqualCondition("name", "name").ifEqualCondition("consistency_level", EACH_QUORUM) .lwtResultListener(listener)); final LWTResultListener.LWTResult LWTResult = atomicCASResult.get(); assertThat(LWTResult).isNotNull(); assertThat(LWTResult.operation()).isEqualTo(UPDATE); assertThat(LWTResult.currentValues()).isEqualTo(expectedCurrentValues); assertThat(LWTResult.toString()).isEqualTo( "CAS operation UPDATE cannot be applied. Current values are: {[applied]=false, consistency_level=EACH_QUORUM, name=John}"); } @Test public void should_notify_listener_when_failing_cas_update_with_ttl() throws Exception { //Given final AtomicReference<LWTResultListener.LWTResult> atomicCASResult = new AtomicReference(null); LWTResultListener listener = new LWTResultListener() { @Override public void onSuccess() { } @Override public void onError(LWTResult lwtResult) { atomicCASResult.compareAndSet(null, lwtResult); } }; final EntityWithEnum entityWithEnum = new EntityWithEnum(10L, "John", EACH_QUORUM); final EntityWithEnum managed = manager.insert(entityWithEnum); Map<String, Object> expectedCurrentValues = ImmutableMap.<String, Object>of("[applied]", false, "consistency_level", EACH_QUORUM.name(), "name", "John"); managed.setName("Helen"); //When manager.update(managed, ifEqualCondition("name", "name").ifEqualCondition("consistency_level", EACH_QUORUM) .lwtResultListener(listener).withTtl(100)); final LWTResultListener.LWTResult LWTResult = atomicCASResult.get(); assertThat(LWTResult).isNotNull(); assertThat(LWTResult.operation()).isEqualTo(UPDATE); assertThat(LWTResult.currentValues()).isEqualTo(expectedCurrentValues); assertThat(LWTResult.toString()).isEqualTo( "CAS operation UPDATE cannot be applied. Current values are: {[applied]=false, consistency_level=EACH_QUORUM, name=John}"); } @Test public void should_update_set_with_cas_condition() throws Exception { //Given CompleteBean entity = builder().randomId().name("John").addFollowers("Paul", "Andrew").buid(); final CompleteBean managed = manager.insert(entity); managed.getFollowers().add("Helen"); managed.getFollowers().remove("Paul"); //When manager.update(managed, ifEqualCondition("name", "John").withTtl(100)); //Then final CompleteBean actual = manager.find(CompleteBean.class, entity.getId()); assertThat(actual.getFollowers()).containsOnly("Helen", "Andrew"); } /** * Ignore until https://issues.apache.org/jira/browse/CASSANDRA-7499 is solved * @throws Exception */ @Ignore @Test public void should_update_list_at_index_with_cas_condition() throws Exception { //Given CompleteBean entity = builder().randomId().name("John").addFriends("Paul", "Andrew").buid(); final CompleteBean managed = manager.insert(entity); managed.getFriends().set(0, "Helen"); managed.getFriends().set(1, null); //When manager.update(managed, ifEqualCondition("name", "John").withTtl(100)); //Then final CompleteBean actual = manager.find(CompleteBean.class, entity.getId()); assertThat(actual.getFriends()).containsExactly("Helen"); } @Test public void should_notify_listener_on_LWT_update_failure() throws Exception { //Given final AtomicReference<LWTResultListener.LWTResult> atomicLWTResult = new AtomicReference(null); LWTResultListener listener = new LWTResultListener() { @Override public void onSuccess() { } @Override public void onError(LWTResult lwtResult) { atomicLWTResult.compareAndSet(null, lwtResult); } }; Map<String, Object> expectedCurrentValues = ImmutableMap.<String, Object>of("[applied]", false, "name", "John"); CompleteBean entity = builder().randomId().name("John").addFollowers("Paul", "Andrew").buid(); final CompleteBean managed = manager.insert(entity); managed.getFollowers().add("Helen"); //When manager.update(managed, ifEqualCondition("name", "Helen").lwtResultListener(listener)); //Then final LWTResultListener.LWTResult LWTResult = atomicLWTResult.get(); assertThat(LWTResult).isNotNull(); assertThat(LWTResult.operation()).isEqualTo(UPDATE); assertThat(LWTResult.currentValues()).isEqualTo(expectedCurrentValues); } @Test public void should_notify_listener_when_LWT_error_on_native_query() throws Exception { //Given final AtomicReference<LWTResultListener.LWTResult> atomicLWTResult = new AtomicReference(null); LWTResultListener listener = new LWTResultListener() { @Override public void onSuccess() { } @Override public void onError(LWTResult lwtResult) { atomicLWTResult.compareAndSet(null, lwtResult); } }; Map<String, Object> expectedCurrentValues = ImmutableMap.<String, Object>of("[applied]", false, "name", "John"); CompleteBean entity = builder().randomId().name("John").buid(); manager.insert(entity); final RegularStatement statement = update("CompleteBean").with(set("name", "Helen")) .where(eq("id", entity.getId())).onlyIf(eq("name", "Andrew")); //When final NativeQuery nativeQuery = manager.nativeQuery(statement, lwtResultListener(listener)); nativeQuery.execute(); //Then final LWTResultListener.LWTResult LWTResult = atomicLWTResult.get(); assertThat(LWTResult).isNotNull(); assertThat(LWTResult.operation()).isEqualTo(UPDATE); assertThat(LWTResult.currentValues()).isEqualTo(expectedCurrentValues); } @Test public void should_delete_if_exists() throws Exception { //Given CompleteBean entity = builder().randomId().name("John").buid(); manager.insert(entity); //When manager.deleteById(CompleteBean.class, entity.getId(), ifExists()); } @Test(expected = AchillesLightWeightTransactionException.class) public void should_exception_when_deleting_non_existing() throws Exception { manager.deleteById(CompleteBean.class, 10L, ifExists()); } @Test public void should_delete_with_lwt_conditions() throws Exception { //Given CompleteBean entity = builder().randomId().name("John").age(33L).buid(); manager.insert(entity); //When manager.deleteById(CompleteBean.class, entity.getId(), ifEqualCondition("name", "John").ifEqualCondition("age_in_years", 33L)); //Then assertThat(manager.find(CompleteBean.class, entity.getId())).isNull(); } }