#437 - Add example for Cassandra Lifecycle Events.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.springdata.cassandra.convert;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import org.springframework.data.cassandra.core.mapping.Element;
|
||||
import org.springframework.data.cassandra.core.mapping.Tuple;
|
||||
|
||||
/**
|
||||
* Simple mapped tuple.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Tuple
|
||||
public class Address {
|
||||
|
||||
@Element(0) String address;
|
||||
@Element(1) String city;
|
||||
@Element(2) String zip;
|
||||
}
|
||||
@@ -17,7 +17,9 @@ package example.springdata.cassandra.convert;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Currency;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.cassandra.core.mapping.Table;
|
||||
@@ -35,4 +37,7 @@ public class Addressbook {
|
||||
|
||||
Contact me;
|
||||
List<Contact> friends;
|
||||
|
||||
Address address;
|
||||
Map<Integer, Currency> preferredCurrencies;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package example.springdata.cassandra.convert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Currency;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
@@ -46,6 +47,8 @@ class ConverterConfiguration {
|
||||
converters.add(new PersonWriteConverter());
|
||||
converters.add(new PersonReadConverter());
|
||||
converters.add(new CustomAddressbookReadConverter());
|
||||
converters.add(CurrencyToStringConverter.INSTANCE);
|
||||
converters.add(StringToCurrencyConverter.INSTANCE);
|
||||
|
||||
return new CassandraCustomConversions(converters);
|
||||
}
|
||||
@@ -98,4 +101,23 @@ class ConverterConfiguration {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
enum StringToCurrencyConverter implements Converter<String, Currency> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public Currency convert(String source) {
|
||||
return Currency.getInstance(source);
|
||||
}
|
||||
}
|
||||
|
||||
enum CurrencyToStringConverter implements Converter<Currency, String> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public String convert(Currency source) {
|
||||
return source.getCurrencyCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.springdata.cassandra.events;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Basic {@link Configuration} to create the necessary schema for the {@link User} table.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EntityScan(basePackageClasses = User.class)
|
||||
class BasicConfiguration {
|
||||
|
||||
@Bean
|
||||
LoggingEventListener listener() {
|
||||
return new LoggingEventListener();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.springdata.cassandra.events;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.data.cassandra.core.mapping.event.AbstractCassandraEventListener;
|
||||
import org.springframework.data.cassandra.core.mapping.event.AfterConvertEvent;
|
||||
import org.springframework.data.cassandra.core.mapping.event.AfterDeleteEvent;
|
||||
import org.springframework.data.cassandra.core.mapping.event.AfterLoadEvent;
|
||||
import org.springframework.data.cassandra.core.mapping.event.AfterSaveEvent;
|
||||
import org.springframework.data.cassandra.core.mapping.event.BeforeDeleteEvent;
|
||||
import org.springframework.data.cassandra.core.mapping.event.BeforeSaveEvent;
|
||||
|
||||
/**
|
||||
* {@link ApplicationListener} for Cassandra mapping events logging the events.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class LoggingEventListener extends AbstractCassandraEventListener<Object> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LoggingEventListener.class);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.core.mapping.event.AbstractCassandraEventListener#onBeforeSave(org.springframework.data.cassandra.core.mapping.event.BeforeSaveEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onBeforeSave(BeforeSaveEvent<Object> event) {
|
||||
LOGGER.info("onBeforeSave: {}, {}", event.getSource(), event.getStatement());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.core.mapping.event.AbstractCassandraEventListener#onAfterSave(org.springframework.data.cassandra.core.mapping.event.AfterSaveEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onAfterSave(AfterSaveEvent<Object> event) {
|
||||
LOGGER.info("onAfterSave: {}", event.getSource());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.core.mapping.event.AbstractCassandraEventListener#onBeforeDelete(org.springframework.data.cassandra.core.mapping.event.BeforeDeleteEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onBeforeDelete(BeforeDeleteEvent<Object> event) {
|
||||
LOGGER.info("onBeforeDelete: {}", event.getSource());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.core.mapping.event.AbstractCassandraEventListener#onAfterDelete(org.springframework.data.cassandra.core.mapping.event.AfterDeleteEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onAfterDelete(AfterDeleteEvent<Object> event) {
|
||||
LOGGER.info("onAfterDelete: {}", event.getSource());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.core.mapping.event.AbstractCassandraEventListener#onAfterLoad(org.springframework.data.cassandra.core.mapping.event.AfterLoadEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onAfterLoad(AfterLoadEvent<Object> event) {
|
||||
LOGGER.info("onAfterLoad: {}", event.getSource());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.core.mapping.event.AbstractCassandraEventListener#onAfterConvert(org.springframework.data.cassandra.core.mapping.event.AfterConvertEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onAfterConvert(AfterConvertEvent<Object> event) {
|
||||
LOGGER.info("onAfterConvert: {}", event.getSource());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.springdata.cassandra.events;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import org.springframework.data.cassandra.core.mapping.PrimaryKey;
|
||||
import org.springframework.data.cassandra.core.mapping.Table;
|
||||
|
||||
/**
|
||||
* Sample user class.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(value = "users")
|
||||
public class User {
|
||||
|
||||
private @PrimaryKey long id;
|
||||
|
||||
private String firstname;
|
||||
private String lastname;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Package usage of Lifecycle events.
|
||||
*/
|
||||
package example.springdata.cassandra.events;
|
||||
@@ -20,6 +20,9 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import example.springdata.cassandra.util.CassandraKeyspace;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Currency;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
@@ -31,6 +34,7 @@ import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.datastax.driver.core.Row;
|
||||
import com.datastax.driver.core.TupleValue;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
|
||||
/**
|
||||
@@ -45,8 +49,8 @@ public class ConversionIntegrationTests {
|
||||
@Autowired CassandraOperations operations;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
operations.getCqlOperations().execute("TRUNCATE addressbook");
|
||||
public void setUp() {
|
||||
operations.truncate(Addressbook.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,4 +118,41 @@ public class ConversionIntegrationTests {
|
||||
assertThat(loaded.getTheId()).isEqualTo(addressbook.getId());
|
||||
assertThat(loaded.getMyDetailsAsJson()).contains("\"firstname\":\"Walter\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and stores a new {@link Addressbook} inside of Cassandra writing map and tuple columns.
|
||||
*/
|
||||
@Test
|
||||
public void shouldWriteConvertedMapsAndTuples() {
|
||||
|
||||
Addressbook addressbook = new Addressbook();
|
||||
addressbook.setId("private");
|
||||
|
||||
Map<Integer, Currency> preferredCurrencies = new HashMap<>();
|
||||
preferredCurrencies.put(1, Currency.getInstance("USD"));
|
||||
preferredCurrencies.put(2, Currency.getInstance("EUR"));
|
||||
|
||||
Address address = new Address();
|
||||
address.setAddress("3828 Piermont Dr");
|
||||
address.setCity("Albuquerque");
|
||||
address.setZip("87111");
|
||||
|
||||
addressbook.setPreferredCurrencies(preferredCurrencies);
|
||||
addressbook.setAddress(address);
|
||||
|
||||
operations.insert(addressbook);
|
||||
|
||||
Row row = operations.selectOne(QueryBuilder.select().from("addressbook"), Row.class);
|
||||
|
||||
assertThat(row).isNotNull();
|
||||
|
||||
TupleValue tupleValue = row.getTupleValue("address");
|
||||
assertThat(tupleValue.getString(0)).isEqualTo(address.getAddress());
|
||||
assertThat(tupleValue.getString(1)).isEqualTo(address.getCity());
|
||||
assertThat(tupleValue.getString(2)).isEqualTo(address.getZip());
|
||||
|
||||
Map<Integer, String> rawPreferredCurrencies = row.getMap("preferredCurrencies", Integer.class, String.class);
|
||||
|
||||
assertThat(rawPreferredCurrencies).containsEntry(1, "USD").containsEntry(2, "EUR");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2018 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 example.springdata.cassandra.events;
|
||||
|
||||
import example.springdata.cassandra.util.CassandraKeyspace;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.data.cassandra.core.query.Query;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Test showing differences between fetching results as {@link List} and {@link Stream streaming} results using
|
||||
* Cassandra Lifecyle Events.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = BasicConfiguration.class)
|
||||
public class LifecycleEventsTests {
|
||||
|
||||
@ClassRule public final static CassandraKeyspace CASSANDRA_KEYSPACE = CassandraKeyspace.onLocalhost();
|
||||
|
||||
@Autowired CassandraOperations operations;
|
||||
|
||||
@Test
|
||||
public void shouldStreamEntities() {
|
||||
|
||||
insertEntities();
|
||||
|
||||
Stream<User> userStream = operations.stream(Query.empty(), User.class);
|
||||
userStream.forEach(System.out::println);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnEntitiesAsList() {
|
||||
|
||||
insertEntities();
|
||||
|
||||
List<User> userStream = operations.select(Query.empty(), User.class);
|
||||
userStream.forEach(System.out::println);
|
||||
}
|
||||
|
||||
private void insertEntities() {
|
||||
|
||||
User walter = new User(1, "Walter", "White");
|
||||
User skyler = new User(2, "Skyler", "White");
|
||||
User jesse = new User(3, "Jesse Pinkman", "Jesse Pinkman");
|
||||
|
||||
operations.truncate(User.class);
|
||||
|
||||
operations.insert(walter);
|
||||
operations.insert(skyler);
|
||||
operations.insert(jesse);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user