info.archinnov.achilles.test.integration.tests.SchemaUpdateIT.java Source code

Java tutorial

Introduction

Here is the source code for info.archinnov.achilles.test.integration.tests.SchemaUpdateIT.java

Source

/*
 * 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 info.archinnov.achilles.embedded.ServerStarter.CASSANDRA_EMBEDDED;
import static info.archinnov.achilles.persistence.PersistenceManagerFactory.PersistenceManagerFactoryBuilder;
import static org.fest.assertions.api.Assertions.assertThat;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import info.archinnov.achilles.annotations.*;
import org.apache.commons.lang3.RandomUtils;
import org.junit.Test;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;
import com.google.common.collect.ImmutableMap;
import info.archinnov.achilles.embedded.CassandraEmbeddedServerBuilder;
import info.archinnov.achilles.exception.AchillesInvalidTableException;
import info.archinnov.achilles.internal.utils.UUIDGen;
import info.archinnov.achilles.persistence.PersistenceManager;
import info.archinnov.achilles.persistence.PersistenceManagerFactory;
import info.archinnov.achilles.test.integration.entity.CompleteBean;
import info.archinnov.achilles.type.Counter;
import info.archinnov.achilles.type.CounterBuilder;

public class SchemaUpdateIT {

    @Test
    public void should_allow_dynamic_schema_update() throws Exception {
        //Given
        Long id = RandomUtils.nextLong(0, Long.MAX_VALUE);
        final Session session = CassandraEmbeddedServerBuilder.noEntityPackages()
                .withKeyspaceName("schema_dynamic_update").cleanDataFilesAtStartup(true).buildNativeSessionOnly();
        session.execute("DROP TABLE IF EXISTS new_simple_field");
        session.execute("DROP INDEX IF EXISTS field_index");
        session.execute("CREATE TABLE new_simple_field(id bigint PRIMARY KEY, existing_field text)");
        session.execute("CREATE INDEX field_index ON schema_dynamic_update.new_simple_field(existing_field)");

        //When
        final PersistenceManagerFactory pmf = PersistenceManagerFactoryBuilder.builder(session.getCluster())
                .withNativeSession(session).withEntities(Arrays.<Class<?>>asList(EntityWithNewSimpleField.class))
                .enableSchemaUpdate(false)
                .enableSchemaUpdateForTables(ImmutableMap.of("schema_dynamic_update.new_simple_field", true))
                .relaxIndexValidation(true).build();

        final PersistenceManager pm = pmf.createPersistenceManager();
        pm.insert(new EntityWithNewSimpleField(id, "existing", "new"));

        //Then
        final EntityWithNewSimpleField found = pm.find(EntityWithNewSimpleField.class, id);

        assertThat(found).isNotNull();
        assertThat(found.getUnmappedField()).isEqualTo("UNMAPPED");

        assertThat(pm.find(EntityWithNewSimpleField.class, id).getUnmappedField()).isEqualTo("UNMAPPED");

        session.close();
    }

    @Test
    public void should_allow_dynamic_schema_update_for_cluster_counter() throws Exception {
        //Given
        Long id = RandomUtils.nextLong(0, Long.MAX_VALUE);
        UUID date = UUIDGen.getTimeUUID();

        final Session session = CassandraEmbeddedServerBuilder
                .withEntities(Arrays.<Class<?>>asList(CompleteBean.class))
                .withKeyspaceName("schema_dynamic_update_counter").cleanDataFilesAtStartup(true)
                .buildNativeSessionOnly();
        session.execute("DROP TABLE IF EXISTS new_counter_field");
        session.execute(
                "CREATE TABLE new_counter_field(id bigint, date timeuuid, existing_counter counter, PRIMARY KEY(id,date))");

        //When
        final PersistenceManagerFactory pmf = PersistenceManagerFactoryBuilder.builder(session.getCluster())
                .withEntities(Arrays.<Class<?>>asList(ClusteredCounterEntityWithNewCounterField.class))
                .enableSchemaUpdate(true).build();

        final PersistenceManager pm = pmf.createPersistenceManager();
        pm.insert(new ClusteredCounterEntityWithNewCounterField(id, date, CounterBuilder.incr(12L)));

        //Then
        assertThat(pm.find(ClusteredCounterEntityWithNewCounterField.class,
                new ClusteredCounterEntityWithNewCounterField.Compound(id, date))).isNotNull();

        session.close();
    }

    @Test(expected = AchillesInvalidTableException.class)
    public void should_fail_bootstrapping_if_schema_update_forbidden_for_entity() throws Exception {
        //Given
        final Session session = CassandraEmbeddedServerBuilder.noEntityPackages()
                .withKeyspaceName("schema_dynamic_update_fail").cleanDataFilesAtStartup(true)
                .buildNativeSessionOnly();
        session.execute("DROP TABLE IF EXISTS new_simple_field");
        session.execute("CREATE TABLE new_simple_field(id bigint PRIMARY KEY, existing_field text)");

        //When
        PersistenceManagerFactoryBuilder.builder(session.getCluster())
                .withEntities(Arrays.<Class<?>>asList(EntityWithNewSimpleField.class))
                .withKeyspaceName("schema_dynamic_update_fail").enableSchemaUpdate(true)
                .enableSchemaUpdateForTables(ImmutableMap.of("schema_dynamic_update_fail.new_simple_field", false))
                .build();

        session.close();
    }

    @Test(expected = AchillesInvalidTableException.class)
    public void should_fail_bootstrapping_if_index_validation_fails() throws Exception {
        //Given
        final Session session = CassandraEmbeddedServerBuilder.noEntityPackages()
                .withKeyspaceName("schema_dynamic_update").cleanDataFilesAtStartup(true).buildNativeSessionOnly();

        //When
        PersistenceManagerFactoryBuilder.builder(session.getCluster())
                .withEntities(Arrays.<Class<?>>asList(EntityWithNewSimpleField.class)).enableSchemaUpdate(true)
                .enableSchemaUpdateForTables(ImmutableMap.of("schema_dynamic_update.new_simple_field", false))
                .relaxIndexValidation(false).build();

        session.close();
    }

    @Entity(keyspace = "schema_dynamic_update", table = "new_simple_field")
    public static class EntityWithNewSimpleField {

        @PartitionKey
        private Long id;

        @Column(name = "existing_field")
        private String existingField;

        private String unmappedField = "UNMAPPED";

        @Column(name = "new_field")
        private String newField;

        @Column(name = "new_list")
        private List<String> newList;

        @Column(name = "new_set")
        private Set<String> newSet;

        @Column(name = "new_map")
        private Map<Integer, String> newMap;

        public EntityWithNewSimpleField() {
        }

        public EntityWithNewSimpleField(Long id, String existingField, String newField) {
            this.id = id;
            this.existingField = existingField;
            this.newField = newField;
        }

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getExistingField() {
            return existingField;
        }

        public void setExistingField(String existingField) {
            this.existingField = existingField;
        }

        public String getUnmappedField() {
            return unmappedField;
        }

        public void setUnmappedField(String unmappedField) {
            this.unmappedField = unmappedField;
        }

        public String getNewField() {
            return newField;
        }

        public void setNewField(String newField) {
            this.newField = newField;
        }

        public List<String> getNewList() {
            return newList;
        }

        public void setNewList(List<String> newList) {
            this.newList = newList;
        }

        public Set<String> getNewSet() {
            return newSet;
        }

        public void setNewSet(Set<String> newSet) {
            this.newSet = newSet;
        }

        public Map<Integer, String> getNewMap() {
            return newMap;
        }

        public void setNewMap(Map<Integer, String> newMap) {
            this.newMap = newMap;
        }
    }

    @Entity(keyspace = "schema_dynamic_update_counter", table = "new_counter_field")
    public static class ClusteredCounterEntityWithNewCounterField {

        @CompoundPrimaryKey
        private Compound id;

        @Column(name = "existing_counter")
        private Counter existingCounter;

        @Column(name = "new_counter_1")
        private Counter newCounter1;

        @Column(name = "new_counter_2")
        private Counter newCounter2;

        public ClusteredCounterEntityWithNewCounterField() {
        }

        public ClusteredCounterEntityWithNewCounterField(Long id, UUID date, Counter existingCounter) {
            this.id = new Compound(id, date);
            this.existingCounter = existingCounter;
        }

        public Compound getId() {
            return id;
        }

        public void setId(Compound id) {
            this.id = id;
        }

        public Counter getExistingCounter() {
            return existingCounter;
        }

        public void setExistingCounter(Counter existingCounter) {
            this.existingCounter = existingCounter;
        }

        public Counter getNewCounter1() {
            return newCounter1;
        }

        public void setNewCounter1(Counter newCounter1) {
            this.newCounter1 = newCounter1;
        }

        public Counter getNewCounter2() {
            return newCounter2;
        }

        public void setNewCounter2(Counter newCounter2) {
            this.newCounter2 = newCounter2;
        }

        public static class Compound {

            @PartitionKey
            private Long id;

            @ClusteringColumn
            @TimeUUID
            private UUID date;

            public Compound() {
            }

            public Compound(Long id, UUID date) {
                this.id = id;
                this.date = date;
            }

            public Long getId() {
                return id;
            }

            public void setId(Long id) {
                this.id = id;
            }

            public UUID getDate() {
                return date;
            }

            public void setDate(UUID date) {
                this.date = date;
            }
        }

    }

    @Entity(table = "entity_with_index")
    public static class EntityWithIndex {

        @PartitionKey
        private Long id;

        @Column
        private String name;

        public Long getId() {
            return id;
        }

        public void setId(Long id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}