group persistence modules (#2890)

* move security content from spring-security-rest-full

* swagger update

* move query language to new module

* rename spring-security-rest-full to spring-rest-full

* group persistence modules
This commit is contained in:
Doha2012
2017-10-30 00:07:04 +02:00
committed by Grzegorz Piwowarek
parent dbeb5f8ba4
commit 26c50909be
185 changed files with 33 additions and 20 deletions
@@ -0,0 +1,2 @@
### Relevant Articles:
- [A Guide to Cassandra with Java](http://www.baeldung.com/cassandra-with-java)
@@ -0,0 +1,91 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>cassandra-java-client</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>cassandra-java-client</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<dependencies>
<!-- Cassandra -->
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>${cassandra-driver-core.version}</version>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.cassandraunit/cassandra-unit -->
<dependency>
<groupId>org.cassandraunit</groupId>
<artifactId>cassandra-unit</artifactId>
<version>${cassandra-unit.version}</version>
</dependency>
<!-- This guava version is required for cassandra-unit 3.0.0.1 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
<build>
<finalName>java-cassandra</finalName>
</build>
<profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*LiveTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<guava.version>19.0</guava.version>
<!-- Cassandra -->
<cassandra-driver-core.version>3.1.2</cassandra-driver-core.version>
<cassandra-unit.version>3.1.1.0</cassandra-unit.version>
</properties>
</project>
@@ -0,0 +1,44 @@
package com.baeldung.cassandra.java.client;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baeldung.cassandra.java.client.domain.Book;
import com.baeldung.cassandra.java.client.repository.BookRepository;
import com.baeldung.cassandra.java.client.repository.KeyspaceRepository;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.utils.UUIDs;
public class CassandraClient {
private static final Logger LOG = LoggerFactory.getLogger(CassandraClient.class);
public static void main(String args[]) {
CassandraConnector connector = new CassandraConnector();
connector.connect("127.0.0.1", null);
Session session = connector.getSession();
KeyspaceRepository sr = new KeyspaceRepository(session);
sr.createKeyspace("library", "SimpleStrategy", 1);
sr.useKeyspace("library");
BookRepository br = new BookRepository(session);
br.createTable();
br.alterTablebooks("publisher", "text");
br.createTableBooksByTitle();
Book book = new Book(UUIDs.timeBased(), "Effective Java", "Joshua Bloch", "Programming");
br.insertBookBatch(book);
br.selectAll().forEach(o -> LOG.info("Title in books: " + o.getTitle()));
br.selectAllBookByTitle().forEach(o -> LOG.info("Title in booksByTitle: " + o.getTitle()));
br.deletebookByTitle("Effective Java");
br.deleteTable("books");
br.deleteTable("booksByTitle");
sr.deleteKeyspace("library");
connector.close();
}
}
@@ -0,0 +1,51 @@
package com.baeldung.cassandra.java.client;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Cluster.Builder;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.Metadata;
import com.datastax.driver.core.Session;
/**
*
* This is an implementation of a simple Java client.
*
*/
public class CassandraConnector {
private static final Logger LOG = LoggerFactory.getLogger(CassandraConnector.class);
private Cluster cluster;
private Session session;
public void connect(final String node, final Integer port) {
Builder b = Cluster.builder().addContactPoint(node);
if (port != null) {
b.withPort(port);
}
cluster = b.build();
Metadata metadata = cluster.getMetadata();
LOG.info("Cluster name: " + metadata.getClusterName());
for (Host host : metadata.getAllHosts()) {
LOG.info("Datacenter: " + host.getDatacenter() + " Host: " + host.getAddress() + " Rack: " + host.getRack());
}
session = cluster.connect();
}
public Session getSession() {
return this.session;
}
public void close() {
session.close();
cluster.close();
}
}
@@ -0,0 +1,66 @@
package com.baeldung.cassandra.java.client.domain;
import java.util.UUID;
public class Book {
private UUID id;
private String title;
private String author;
private String subject;
private String publisher;
Book() {
}
public Book(UUID id, String title, String author, String subject) {
this.id = id;
this.title = title;
this.author = author;
this.subject = subject;
}
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getPublisher() {
return publisher;
}
public void setPublisher(String publisher) {
this.publisher = publisher;
}
}
@@ -0,0 +1,173 @@
package com.baeldung.cassandra.java.client.repository;
import java.util.ArrayList;
import java.util.List;
import com.baeldung.cassandra.java.client.domain.Book;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
public class BookRepository {
private static final String TABLE_NAME = "books";
private static final String TABLE_NAME_BY_TITLE = TABLE_NAME + "ByTitle";
private Session session;
public BookRepository(Session session) {
this.session = session;
}
/**
* Creates the books table.
*/
public void createTable() {
StringBuilder sb = new StringBuilder("CREATE TABLE IF NOT EXISTS ").append(TABLE_NAME).append("(").append("id uuid PRIMARY KEY, ").append("title text,").append("author text,").append("subject text);");
final String query = sb.toString();
session.execute(query);
}
/**
* Creates the books table.
*/
public void createTableBooksByTitle() {
StringBuilder sb = new StringBuilder("CREATE TABLE IF NOT EXISTS ").append(TABLE_NAME_BY_TITLE).append("(").append("id uuid, ").append("title text,").append("PRIMARY KEY (title, id));");
final String query = sb.toString();
session.execute(query);
}
/**
* Alters the table books and adds an extra column.
*/
public void alterTablebooks(String columnName, String columnType) {
StringBuilder sb = new StringBuilder("ALTER TABLE ").append(TABLE_NAME).append(" ADD ").append(columnName).append(" ").append(columnType).append(";");
final String query = sb.toString();
session.execute(query);
}
/**
* Insert a row in the table books.
*
* @param book
*/
public void insertbook(Book book) {
StringBuilder sb = new StringBuilder("INSERT INTO ").append(TABLE_NAME).append("(id, title, author, subject) ").append("VALUES (").append(book.getId()).append(", '").append(book.getTitle()).append("', '").append(book.getAuthor()).append("', '")
.append(book.getSubject()).append("');");
final String query = sb.toString();
session.execute(query);
}
/**
* Insert a row in the table booksByTitle.
* @param book
*/
public void insertbookByTitle(Book book) {
StringBuilder sb = new StringBuilder("INSERT INTO ").append(TABLE_NAME_BY_TITLE).append("(id, title) ").append("VALUES (").append(book.getId()).append(", '").append(book.getTitle()).append("');");
final String query = sb.toString();
session.execute(query);
}
/**
* Insert a book into two identical tables using a batch query.
*
* @param book
*/
public void insertBookBatch(Book book) {
StringBuilder sb = new StringBuilder("BEGIN BATCH ").append("INSERT INTO ").append(TABLE_NAME).append("(id, title, author, subject) ").append("VALUES (").append(book.getId()).append(", '").append(book.getTitle()).append("', '").append(book.getAuthor())
.append("', '").append(book.getSubject()).append("');").append("INSERT INTO ").append(TABLE_NAME_BY_TITLE).append("(id, title) ").append("VALUES (").append(book.getId()).append(", '").append(book.getTitle()).append("');")
.append("APPLY BATCH;");
final String query = sb.toString();
session.execute(query);
}
/**
* Select book by id.
*
* @return
*/
public Book selectByTitle(String title) {
StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME_BY_TITLE).append(" WHERE title = '").append(title).append("';");
final String query = sb.toString();
ResultSet rs = session.execute(query);
List<Book> books = new ArrayList<Book>();
for (Row r : rs) {
Book s = new Book(r.getUUID("id"), r.getString("title"), null, null);
books.add(s);
}
return books.get(0);
}
/**
* Select all books from books
*
* @return
*/
public List<Book> selectAll() {
StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME);
final String query = sb.toString();
ResultSet rs = session.execute(query);
List<Book> books = new ArrayList<Book>();
for (Row r : rs) {
Book book = new Book(r.getUUID("id"), r.getString("title"), r.getString("author"), r.getString("subject"));
books.add(book);
}
return books;
}
/**
* Select all books from booksByTitle
* @return
*/
public List<Book> selectAllBookByTitle() {
StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME_BY_TITLE);
final String query = sb.toString();
ResultSet rs = session.execute(query);
List<Book> books = new ArrayList<Book>();
for (Row r : rs) {
Book book = new Book(r.getUUID("id"), r.getString("title"), null, null);
books.add(book);
}
return books;
}
/**
* Delete a book by title.
*/
public void deletebookByTitle(String title) {
StringBuilder sb = new StringBuilder("DELETE FROM ").append(TABLE_NAME_BY_TITLE).append(" WHERE title = '").append(title).append("';");
final String query = sb.toString();
session.execute(query);
}
/**
* Delete table.
*
* @param tableName the name of the table to delete.
*/
public void deleteTable(String tableName) {
StringBuilder sb = new StringBuilder("DROP TABLE IF EXISTS ").append(tableName);
final String query = sb.toString();
session.execute(query);
}
}
@@ -0,0 +1,49 @@
package com.baeldung.cassandra.java.client.repository;
import com.datastax.driver.core.Session;
/**
* Repository to handle the Cassandra schema.
*
*/
public class KeyspaceRepository {
private Session session;
public KeyspaceRepository(Session session) {
this.session = session;
}
/**
* Method used to create any keyspace - schema.
*
* @param schemaName the name of the schema.
* @param replicatioonStrategy the replication strategy.
* @param numberOfReplicas the number of replicas.
*
*/
public void createKeyspace(String keyspaceName, String replicatioonStrategy, int numberOfReplicas) {
StringBuilder sb = new StringBuilder("CREATE KEYSPACE IF NOT EXISTS ").append(keyspaceName).append(" WITH replication = {").append("'class':'").append(replicatioonStrategy).append("','replication_factor':").append(numberOfReplicas).append("};");
final String query = sb.toString();
session.execute(query);
}
public void useKeyspace(String keyspace) {
session.execute("USE " + keyspace);
}
/**
* Method used to delete the specified schema.
* It results in the immediate, irreversable removal of the keyspace, including all tables and data contained in the keyspace.
*
* @param schemaName the name of the keyspace to delete.
*/
public void deleteKeyspace(String keyspaceName) {
StringBuilder sb = new StringBuilder("DROP KEYSPACE ").append(keyspaceName);
final String query = sb.toString();
session.execute(query);
}
}
@@ -0,0 +1,174 @@
package com.baeldung.cassandra.java.client.repository;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.baeldung.cassandra.java.client.CassandraConnector;
import com.baeldung.cassandra.java.client.domain.Book;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.InvalidQueryException;
import com.datastax.driver.core.utils.UUIDs;
public class BookRepositoryIntegrationTest {
private KeyspaceRepository schemaRepository;
private BookRepository bookRepository;
private Session session;
final String KEYSPACE_NAME = "testLibrary";
final String BOOKS = "books";
final String BOOKS_BY_TITLE = "booksByTitle";
@BeforeClass
public static void init() throws ConfigurationException, TTransportException, IOException, InterruptedException {
// Start an embedded Cassandra Server
EmbeddedCassandraServerHelper.startEmbeddedCassandra(20000L);
}
@Before
public void connect() {
CassandraConnector client = new CassandraConnector();
client.connect("127.0.0.1", 9142);
this.session = client.getSession();
schemaRepository = new KeyspaceRepository(session);
schemaRepository.createKeyspace(KEYSPACE_NAME, "SimpleStrategy", 1);
schemaRepository.useKeyspace(KEYSPACE_NAME);
bookRepository = new BookRepository(session);
}
@Test
public void whenCreatingATable_thenCreatedCorrectly() {
bookRepository.deleteTable(BOOKS);
bookRepository.createTable();
ResultSet result = session.execute("SELECT * FROM " + KEYSPACE_NAME + "." + BOOKS + ";");
// Collect all the column names in one list.
List<String> columnNames = result.getColumnDefinitions().asList().stream().map(cl -> cl.getName()).collect(Collectors.toList());
assertEquals(columnNames.size(), 4);
assertTrue(columnNames.contains("id"));
assertTrue(columnNames.contains("title"));
assertTrue(columnNames.contains("author"));
assertTrue(columnNames.contains("subject"));
}
@Test
public void whenAlteringTable_thenAddedColumnExists() {
bookRepository.deleteTable(BOOKS);
bookRepository.createTable();
bookRepository.alterTablebooks("publisher", "text");
ResultSet result = session.execute("SELECT * FROM " + KEYSPACE_NAME + "." + BOOKS + ";");
boolean columnExists = result.getColumnDefinitions().asList().stream().anyMatch(cl -> cl.getName().equals("publisher"));
assertTrue(columnExists);
}
@Test
public void whenAddingANewBook_thenBookExists() {
bookRepository.deleteTable(BOOKS_BY_TITLE);
bookRepository.createTableBooksByTitle();
String title = "Effective Java";
String author = "Joshua Bloch";
Book book = new Book(UUIDs.timeBased(), title, author, "Programming");
bookRepository.insertbookByTitle(book);
Book savedBook = bookRepository.selectByTitle(title);
assertEquals(book.getTitle(), savedBook.getTitle());
}
@Test
public void whenAddingANewBookBatch_ThenBookAddedInAllTables() {
// Create table books
bookRepository.deleteTable(BOOKS);
bookRepository.createTable();
// Create table booksByTitle
bookRepository.deleteTable(BOOKS_BY_TITLE);
bookRepository.createTableBooksByTitle();
String title = "Effective Java";
String author = "Joshua Bloch";
Book book = new Book(UUIDs.timeBased(), title, author, "Programming");
bookRepository.insertBookBatch(book);
List<Book> books = bookRepository.selectAll();
assertEquals(1, books.size());
assertTrue(books.stream().anyMatch(b -> b.getTitle().equals("Effective Java")));
List<Book> booksByTitle = bookRepository.selectAllBookByTitle();
assertEquals(1, booksByTitle.size());
assertTrue(booksByTitle.stream().anyMatch(b -> b.getTitle().equals("Effective Java")));
}
@Test
public void whenSelectingAll_thenReturnAllRecords() {
bookRepository.deleteTable(BOOKS);
bookRepository.createTable();
Book book = new Book(UUIDs.timeBased(), "Effective Java", "Joshua Bloch", "Programming");
bookRepository.insertbook(book);
book = new Book(UUIDs.timeBased(), "Clean Code", "Robert C. Martin", "Programming");
bookRepository.insertbook(book);
List<Book> books = bookRepository.selectAll();
assertEquals(2, books.size());
assertTrue(books.stream().anyMatch(b -> b.getTitle().equals("Effective Java")));
assertTrue(books.stream().anyMatch(b -> b.getTitle().equals("Clean Code")));
}
@Test
public void whenDeletingABookByTitle_thenBookIsDeleted() {
bookRepository.deleteTable(BOOKS_BY_TITLE);
bookRepository.createTableBooksByTitle();
Book book = new Book(UUIDs.timeBased(), "Effective Java", "Joshua Bloch", "Programming");
bookRepository.insertbookByTitle(book);
book = new Book(UUIDs.timeBased(), "Clean Code", "Robert C. Martin", "Programming");
bookRepository.insertbookByTitle(book);
bookRepository.deletebookByTitle("Clean Code");
List<Book> books = bookRepository.selectAllBookByTitle();
assertEquals(1, books.size());
assertTrue(books.stream().anyMatch(b -> b.getTitle().equals("Effective Java")));
assertFalse(books.stream().anyMatch(b -> b.getTitle().equals("Clean Code")));
}
@Test(expected = InvalidQueryException.class)
public void whenDeletingATable_thenUnconfiguredTable() {
bookRepository.createTable();
bookRepository.deleteTable(BOOKS);
session.execute("SELECT * FROM " + KEYSPACE_NAME + "." + BOOKS + ";");
}
@AfterClass
public static void cleanup() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
}
@@ -0,0 +1,77 @@
package com.baeldung.cassandra.java.client.repository;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import com.baeldung.cassandra.java.client.CassandraConnector;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Session;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class KeyspaceRepositoryIntegrationTest {
private KeyspaceRepository schemaRepository;
private Session session;
@BeforeClass
public static void init() throws ConfigurationException, TTransportException, IOException, InterruptedException {
// Start an embedded Cassandra Server
EmbeddedCassandraServerHelper.startEmbeddedCassandra(20000L);
}
@Before
public void connect() {
CassandraConnector client = new CassandraConnector();
client.connect("127.0.0.1", 9142);
this.session = client.getSession();
schemaRepository = new KeyspaceRepository(session);
}
@Test
public void whenCreatingAKeyspace_thenCreated() {
String keyspaceName = "testBaeldungKeyspace";
schemaRepository.createKeyspace(keyspaceName, "SimpleStrategy", 1);
// ResultSet result = session.execute("SELECT * FROM system_schema.keyspaces WHERE keyspace_name = 'testBaeldungKeyspace';");
ResultSet result = session.execute("SELECT * FROM system_schema.keyspaces;");
// Check if the Keyspace exists in the returned keyspaces.
List<String> matchedKeyspaces = result.all().stream().filter(r -> r.getString(0).equals(keyspaceName.toLowerCase())).map(r -> r.getString(0)).collect(Collectors.toList());
assertEquals(matchedKeyspaces.size(), 1);
assertTrue(matchedKeyspaces.get(0).equals(keyspaceName.toLowerCase()));
}
@Test
public void whenDeletingAKeyspace_thenDoesNotExist() {
String keyspaceName = "testBaeldungKeyspace";
// schemaRepository.createKeyspace(keyspaceName, "SimpleStrategy", 1);
schemaRepository.deleteKeyspace(keyspaceName);
ResultSet result = session.execute("SELECT * FROM system_schema.keyspaces;");
boolean isKeyspaceCreated = result.all().stream().anyMatch(r -> r.getString(0).equals(keyspaceName.toLowerCase()));
assertFalse(isKeyspaceCreated);
}
@AfterClass
public static void cleanup() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
}
@@ -0,0 +1,5 @@
.classpath
.project
.settings
target
build
@@ -0,0 +1,3 @@
## Relevant articles:
- [A Guide to MongoDB with Java](http://www.baeldung.com/java-mongodb)
+77
View File
@@ -0,0 +1,77 @@
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>java-mongodb</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>de.flapdoodle.embedmongo</groupId>
<artifactId>de.flapdoodle.embedmongo</artifactId>
<version>${flapdoodle.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${mongo.version}</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*ManualTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<mongo.version>3.4.1</mongo.version>
<flapdoodle.version>1.11</flapdoodle.version>
</properties>
</project>
@@ -0,0 +1,53 @@
package com.baeldung;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.MongoClient;
public class MongoExample {
public static void main(String[] args) {
MongoClient mongoClient = new MongoClient("localhost", 27017);
DB database = mongoClient.getDB("myMongoDb");
// print existing databases
mongoClient.getDatabaseNames().forEach(System.out::println);
database.createCollection("customers", null);
// print all collections in customers database
database.getCollectionNames().forEach(System.out::println);
// create data
DBCollection collection = database.getCollection("customers");
BasicDBObject document = new BasicDBObject();
document.put("name", "Shubham");
document.put("company", "Baeldung");
collection.insert(document);
// update data
BasicDBObject query = new BasicDBObject();
query.put("name", "Shubham");
BasicDBObject newDocument = new BasicDBObject();
newDocument.put("name", "John");
BasicDBObject updateObject = new BasicDBObject();
updateObject.put("$set", newDocument);
collection.update(query, updateObject);
// read data
BasicDBObject searchQuery = new BasicDBObject();
searchQuery.put("name", "John");
DBCursor cursor = collection.find(searchQuery);
while (cursor.hasNext()) {
System.out.println(cursor.next());
}
// delete data
BasicDBObject deleteQuery = new BasicDBObject();
deleteQuery.put("name", "John");
collection.remove(deleteQuery);
}
}
@@ -0,0 +1,72 @@
package com.baeldung;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;
import de.flapdoodle.embedmongo.MongoDBRuntime;
import de.flapdoodle.embedmongo.MongodExecutable;
import de.flapdoodle.embedmongo.MongodProcess;
import de.flapdoodle.embedmongo.config.MongodConfig;
import de.flapdoodle.embedmongo.distribution.Version;
import de.flapdoodle.embedmongo.runtime.Network;
public class AppIntegrationTest {
private static final String DB_NAME = "myMongoDb";
private MongodExecutable mongodExe;
private MongodProcess mongod;
private Mongo mongo;
private DB db;
private DBCollection collection;
@Before
public void setup() throws Exception {
// Creating Mongodbruntime instance
MongoDBRuntime runtime = MongoDBRuntime.getDefaultInstance();
// Creating MongodbExecutable
mongodExe = runtime.prepare(new MongodConfig(Version.V2_0_1, 12345, Network.localhostIsIPv6()));
// Starting Mongodb
mongod = mongodExe.start();
mongo = new Mongo("localhost", 12345);
// Creating DB
db = mongo.getDB(DB_NAME);
// Creating collection Object and adding values
collection = db.getCollection("customers");
}
@After
public void teardown() throws Exception {
mongod.stop();
mongodExe.cleanup();
}
@Test
public void testAddressPersistance() {
BasicDBObject contact = new BasicDBObject();
contact.put("name", "John");
contact.put("company", "Baeldung");
// Inserting document
collection.insert(contact);
DBCursor cursorDoc = collection.find();
BasicDBObject contact1 = new BasicDBObject();
while (cursorDoc.hasNext()) {
contact1 = (BasicDBObject) cursorDoc.next();
System.out.println(contact1);
}
assertEquals(contact1.get("name"), "John");
}
}
+2
View File
@@ -0,0 +1,2 @@
### Relevant Articles:
- [Introduction to Liquibase Rollback](http://www.baeldung.com/liquibase-rollback)
+48
View File
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>parent-modules</artifactId>
<groupId>com.baeldung</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>liquibase</artifactId>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
<build>
<finalName>baeldung-liquibase-demo</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.2</version>
<configuration>
<propertyFile>liquibase/liquibase.properties</propertyFile>
<changeLogFile>liquibase/db-changelog.xml</changeLogFile>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,69 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
<changeSet id="testRollback" author="baeldung">
<createTable tableName="baeldung_tutorial">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
<column name="author" type="varchar(36)"/>
</createTable>
<rollback>
<dropTable tableName="baeldung_tutorial"/>
</rollback>
</changeSet>
<changeSet id="multiStatementRollback" author="baeldung">
<createTable tableName="baeldung_tutorial2">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
<column name="author" type="varchar(36)"/>
</createTable>
<createTable tableName="baeldung_tutorial3">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
<column name="author" type="varchar(36)"/>
</createTable>
<rollback>
<dropTable tableName="baeldung_tutorial2"/>
<dropTable tableName="baeldung_tutorial3"/>
</rollback>
</changeSet>
<changeSet id="multipleRollbackTags" author="baeldung">
<createTable tableName="baeldung_tutorial4">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
<column name="author" type="varchar(36)"/>
</createTable>
<createTable tableName="baeldung_tutorial5">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
<column name="author" type="varchar(36)"/>
</createTable>
<rollback>
<dropTable tableName="baeldung_tutorial4"/>
</rollback>
<rollback>
<dropTable tableName="baeldung_tutorial5"/>
</rollback>
</changeSet>
<changeSet id="referChangeSetForRollback" author="baeldung">
<dropTable tableName="baeldung_tutorial2"/>
<dropTable tableName="baeldung_tutorial3"/>
<rollback changeSetId="multiStatementRollback" changeSetAuthor="baeldung"/>
</changeSet>
<changeSet id="emptyRollback" author="baeldung">
<createTable tableName="baeldung_tutorial6">
<column name="id" type="int"/>
<column name="heading" type="varchar(36)"/>
<column name="author" type="varchar(36)"/>
</createTable>
<rollback/>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,4 @@
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/baeldung_liquibase
username=root
password=password
+2
View File
@@ -0,0 +1,2 @@
### Relevant Articles:
- [Intro to Querydsl](http://www.baeldung.com/intro-to-querydsl)
+202
View File
@@ -0,0 +1,202 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>querydsl</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>querydsl</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<spring.version>4.3.4.RELEASE</spring.version>
<hibernate.version>5.2.5.Final</hibernate.version>
<hibernate-jpa.version>1.0.0.Final</hibernate-jpa.version>
<querydsl.version>4.1.4</querydsl.version>
<hsqldb.version>2.3.4</hsqldb.version>
<commons-pool.version>1.6</commons-pool.version>
<commons-dbcp.version>1.4</commons-dbcp.version>
<apt-maven-plugin.version>1.1.3</apt-maven-plugin.version>
</properties>
<dependencies>
<!-- QueryDSL -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>${querydsl.version}</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>${querydsl.version}</version>
<scope>provided</scope>
</dependency>
<!-- JPA Persistence Dependencies -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>${hibernate-jpa.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>${commons-dbcp.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>${commons-pool.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- HSQLDB Dependencies -->
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version>
</dependency>
<!-- Spring Dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<type>jar</type>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Compile src folder without annotation processing -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
<!-- QueryDSL plugin -->
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>${apt-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*LiveTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
@@ -0,0 +1,22 @@
package org.baeldung.dao;
import java.util.List;
import java.util.Map;
import org.baeldung.entity.Person;
public interface PersonDao {
public Person save(Person person);
public List<Person> findPersonsByFirstnameQueryDSL(String firstname);
public List<Person> findPersonsByFirstnameAndSurnameQueryDSL(String firstname, String surname);
public List<Person> findPersonsByFirstnameInDescendingOrderQueryDSL(String firstname);
public int findMaxAge();
public Map<String, Integer> findMaxAgeByName();
}
@@ -0,0 +1,68 @@
package org.baeldung.dao;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.baeldung.entity.Person;
import org.baeldung.entity.QPerson;
import org.springframework.stereotype.Repository;
import com.querydsl.core.group.GroupBy;
import com.querydsl.jpa.impl.JPAQuery;
@Repository
public class PersonDaoImpl implements PersonDao {
@PersistenceContext
private EntityManager em;
@Override
public Person save(final Person person) {
em.persist(person);
return person;
}
@Override
public List<Person> findPersonsByFirstnameQueryDSL(final String firstname) {
final JPAQuery<Person> query = new JPAQuery<>(em);
final QPerson person = QPerson.person;
return query.from(person).where(person.firstname.eq(firstname)).fetch();
}
@Override
public List<Person> findPersonsByFirstnameAndSurnameQueryDSL(final String firstname, final String surname) {
final JPAQuery<Person> query = new JPAQuery<>(em);
final QPerson person = QPerson.person;
return query.from(person).where(person.firstname.eq(firstname).and(person.surname.eq(surname))).fetch();
}
@Override
public List<Person> findPersonsByFirstnameInDescendingOrderQueryDSL(final String firstname) {
final JPAQuery<Person> query = new JPAQuery<>(em);
final QPerson person = QPerson.person;
return query.from(person).where(person.firstname.eq(firstname)).orderBy(person.surname.desc()).fetch();
}
@Override
public int findMaxAge() {
final JPAQuery<Person> query = new JPAQuery<>(em);
final QPerson person = QPerson.person;
return query.from(person).select(person.age.max()).fetchFirst();
}
@Override
public Map<String, Integer> findMaxAgeByName() {
final JPAQuery<Person> query = new JPAQuery<>(em);
final QPerson person = QPerson.person;
return query.from(person).transform(GroupBy.groupBy(person.firstname).as(GroupBy.max(person.age)));
}
}
@@ -0,0 +1,69 @@
package org.baeldung.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String firstname;
@Column
private String surname;
@Column
private int age;
Person() {
}
public Person(final String firstname, final String surname) {
this.firstname = firstname;
this.surname = surname;
}
public Person(final String firstname, final String surname, final int age) {
this(firstname, surname);
this.age = age;
}
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(final String firstname) {
this.firstname = firstname;
}
public String getSurname() {
return surname;
}
public void setSurname(final String surname) {
this.surname = surname;
}
public int getAge() {
return age;
}
public void setAge(final int age) {
this.age = age;
}
}
@@ -0,0 +1,56 @@
/*
* (c) Центр ИТ, 2016. Все права защищены.
*/
package org.baeldung.querydsl.intro.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class BlogPost {
@Id
@GeneratedValue
private Long id;
private String title;
private String body;
@ManyToOne
private User user;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String code) {
this.title = code;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
@@ -0,0 +1,55 @@
/*
* (c) Центр ИТ, 2016. Все права защищены.
*/
package org.baeldung.querydsl.intro.entities;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String login;
private Boolean disabled;
@OneToMany(cascade = CascadeType.PERSIST, mappedBy = "user")
private Set<BlogPost> blogPosts = new HashSet<>(0);
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLogin() {
return login;
}
public void setLogin(String name) {
this.login = name;
}
public Set<BlogPost> getBlogPosts() {
return blogPosts;
}
public void setBlogPosts(Set<BlogPost> blogPosts) {
this.blogPosts = blogPosts;
}
public Boolean getDisabled() {
return disabled;
}
public void setDisabled(Boolean disabled) {
this.disabled = disabled;
}
}
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<!-- PersistenceUnit for datastore -->
<persistence-unit name="default" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.transaction.flush_before_completion"
value="true" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider" />
</properties>
</persistence-unit>
<!-- PersistenceUnit for Intro to QueryDSL -->
<persistence-unit name="org.baeldung.querydsl.intro">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:test"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
</properties>
</persistence-unit>
</persistence>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>web - %date [%thread] %-5level %logger{36} - %message%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -0,0 +1,81 @@
package org.baeldung.dao;
import java.util.Map;
import org.baeldung.entity.Person;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
import junit.framework.Assert;
@ContextConfiguration("/test-context.xml")
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@TransactionConfiguration(defaultRollback = true)
public class PersonDaoIntegrationTest {
@Autowired
private PersonDao personDao;
//
@Test
public void testCreation() {
personDao.save(new Person("Erich", "Gamma"));
final Person person = new Person("Kent", "Beck");
personDao.save(person);
personDao.save(new Person("Ralph", "Johnson"));
final Person personFromDb = personDao.findPersonsByFirstnameQueryDSL("Kent").get(0);
Assert.assertEquals(person.getId(), personFromDb.getId());
}
@Test
public void testMultipleFilter() {
personDao.save(new Person("Erich", "Gamma"));
final Person person = personDao.save(new Person("Ralph", "Beck"));
final Person person2 = personDao.save(new Person("Ralph", "Johnson"));
final Person personFromDb = personDao.findPersonsByFirstnameAndSurnameQueryDSL("Ralph", "Johnson").get(0);
Assert.assertNotSame(person.getId(), personFromDb.getId());
Assert.assertEquals(person2.getId(), personFromDb.getId());
}
@Test
public void testOrdering() {
final Person person = personDao.save(new Person("Kent", "Gamma"));
personDao.save(new Person("Ralph", "Johnson"));
final Person person2 = personDao.save(new Person("Kent", "Zivago"));
final Person personFromDb = personDao.findPersonsByFirstnameInDescendingOrderQueryDSL("Kent").get(0);
Assert.assertNotSame(person.getId(), personFromDb.getId());
Assert.assertEquals(person2.getId(), personFromDb.getId());
}
@Test
public void testMaxAge() {
personDao.save(new Person("Kent", "Gamma", 20));
personDao.save(new Person("Ralph", "Johnson", 35));
personDao.save(new Person("Kent", "Zivago", 30));
final int maxAge = personDao.findMaxAge();
Assert.assertTrue(maxAge == 35);
}
@Test
public void testMaxAgeByName() {
personDao.save(new Person("Kent", "Gamma", 20));
personDao.save(new Person("Ralph", "Johnson", 35));
personDao.save(new Person("Kent", "Zivago", 30));
final Map<String, Integer> maxAge = personDao.findMaxAgeByName();
Assert.assertTrue(maxAge.size() == 2);
Assert.assertSame(35, maxAge.get("Ralph"));
Assert.assertSame(30, maxAge.get("Kent"));
}
}
@@ -0,0 +1,215 @@
/*
* (c) Центр ИТ, 2016. Все права защищены.
*/
package org.baeldung.querydsl.intro;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.NumberPath;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.baeldung.querydsl.intro.entities.BlogPost;
import org.baeldung.querydsl.intro.entities.QBlogPost;
import org.baeldung.querydsl.intro.entities.QUser;
import org.baeldung.querydsl.intro.entities.User;
import org.junit.*;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.util.List;
import static org.junit.Assert.*;
public class QueryDSLIntegrationTest {
private static EntityManagerFactory emf;
private EntityManager em;
private JPAQueryFactory queryFactory;
@BeforeClass
public static void populateDatabase() {
emf = Persistence.createEntityManagerFactory("org.baeldung.querydsl.intro");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
User user1 = new User();
user1.setLogin("David");
em.persist(user1);
User user2 = new User();
user2.setLogin("Ash");
em.persist(user2);
User user3 = new User();
user3.setLogin("Call");
em.persist(user3);
User user4 = new User();
user4.setLogin("Bishop");
em.persist(user4);
BlogPost blogPost1 = new BlogPost();
blogPost1.setTitle("Hello World!");
blogPost1.setUser(user1);
em.persist(blogPost1);
BlogPost blogPost2 = new BlogPost();
blogPost2.setTitle("My Second Post");
blogPost2.setUser(user1);
em.persist(blogPost2);
BlogPost blogPost3 = new BlogPost();
blogPost3.setTitle("Hello World!");
blogPost3.setUser(user3);
em.persist(blogPost3);
em.getTransaction().commit();
em.close();
}
@Before
public void setUp() {
em = emf.createEntityManager();
em.getTransaction().begin();
queryFactory = new JPAQueryFactory(em);
}
@Test
public void whenFindByLogin_thenShouldReturnUser() {
QUser user = QUser.user;
User aUser = queryFactory.selectFrom(user)
.where(user.login.eq("David"))
.fetchOne();
assertNotNull(aUser);
assertEquals(aUser.getLogin(), "David");
}
@Test
public void whenUsingOrderBy_thenResultsShouldBeOrdered() {
QUser user = QUser.user;
List<User> users = queryFactory.selectFrom(user)
.orderBy(user.login.asc())
.fetch();
assertEquals(users.size(), 4);
assertEquals(users.get(0).getLogin(), "Ash");
assertEquals(users.get(1).getLogin(), "Bishop");
assertEquals(users.get(2).getLogin(), "Call");
assertEquals(users.get(3).getLogin(), "David");
}
@Test
public void whenGroupingByTitle_thenReturnsTuples() {
QBlogPost blogPost = QBlogPost.blogPost;
NumberPath<Long> count = Expressions.numberPath(Long.class, "c");
List<Tuple> userTitleCounts = queryFactory.select(blogPost.title, blogPost.id.count().as(count))
.from(blogPost)
.groupBy(blogPost.title)
.orderBy(count.desc())
.fetch();
assertEquals("Hello World!", userTitleCounts.get(0).get(blogPost.title));
assertEquals(new Long(2), userTitleCounts.get(0).get(count));
assertEquals("My Second Post", userTitleCounts.get(1).get(blogPost.title));
assertEquals(new Long(1), userTitleCounts.get(1).get(count));
}
@Test
public void whenJoiningWithCondition_thenResultCountShouldMatch() {
QUser user = QUser.user;
QBlogPost blogPost = QBlogPost.blogPost;
List<User> users = queryFactory.selectFrom(user)
.innerJoin(user.blogPosts, blogPost)
.on(blogPost.title.eq("Hello World!"))
.fetch();
assertEquals(2, users.size());
}
@Test
public void whenRefiningWithSubquery_thenResultCountShouldMatch() {
QUser user = QUser.user;
QBlogPost blogPost = QBlogPost.blogPost;
List<User> users = queryFactory.selectFrom(user)
.where(user.id.in(
JPAExpressions.select(blogPost.user.id)
.from(blogPost)
.where(blogPost.title.eq("Hello World!"))))
.fetch();
assertEquals(2, users.size());
}
@Test
public void whenUpdating_thenTheRecordShouldChange() {
QUser user = QUser.user;
queryFactory.update(user)
.where(user.login.eq("Ash"))
.set(user.login, "Ash2")
.set(user.disabled, true)
.execute();
em.getTransaction().commit();
em.getTransaction().begin();
assertEquals(Boolean.TRUE,
queryFactory.select(user.disabled)
.from(user)
.where(user.login.eq("Ash2"))
.fetchOne());
}
@Test
public void whenDeleting_thenTheRecordShouldBeAbsent() {
QUser user = QUser.user;
queryFactory.delete(user)
.where(user.login.eq("Bishop"))
.execute();
em.getTransaction().commit();
em.getTransaction().begin();
assertNull(queryFactory.selectFrom(user)
.where(user.login.eq("Bishop"))
.fetchOne());
}
@After
public void tearDown() {
em.getTransaction().commit();
em.close();
}
@AfterClass
public static void afterClass() {
emf.close();
}
}
@@ -0,0 +1,6 @@
#In memory db
db.username=sa
db.password=
db.driver=org.hsqldb.jdbcDriver
db.url=jdbc:hsqldb:mem:app-db
db.dialect=org.hibernate.dialect.HSQLDialect
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
>
<tx:annotation-driven />
<context:component-scan base-package="org.baeldung" />
<import resource="test-db.xml" />
</beans>
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" default-autowire="byName">
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:db.properties</value>
</list>
</property>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" name="EntityManagerFactory">
<property name="persistenceUnitName" value="default"></property>
<property name="dataSource" ref="dataSource"></property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="${db.dialect}" />
</bean>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" name="TransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
<tx:annotation-driven />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
</beans>
+3
View File
@@ -0,0 +1,3 @@
### Relevant Articles:
- [Intro to Jedis the Java Redis Client Library](http://www.baeldung.com/jedis-java-redis-client-library)
- [A Guide to Redis with Redisson](http://www.baeldung.com/redis-redisson)
+47
View File
@@ -0,0 +1,47 @@
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>redis</artifactId>
<version>0.1-SNAPSHOT</version>
<name>redis</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<dependency>
<groupId>com.github.kstyrc</groupId>
<artifactId>embedded-redis</artifactId>
<version>${embedded-redis.version}</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jedis.version>2.9.0</jedis.version>
<embedded-redis.version>0.6</embedded-redis.version>
</properties>
</project>
@@ -0,0 +1,19 @@
package com.baeldung;
/**
* Created by johnson on 3/9/17.
*/
public class CustomMessage {
private String message;
public CustomMessage() {
}
public CustomMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
@@ -0,0 +1,21 @@
package com.baeldung;
public class Ledger {
public Ledger() {
}
public Ledger(String name) {
this.name = name;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@@ -0,0 +1,21 @@
package com.baeldung;
import org.redisson.api.annotation.REntity;
import org.redisson.api.annotation.RId;
/**
* Created by johnson on 3/9/17.
*/
@REntity
public class LedgerLiveObject {
@RId
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@@ -0,0 +1,17 @@
package com.baeldung;
import java.util.Arrays;
import java.util.List;
/**
* Created by johnson on 3/9/17.
*/
public class LedgerServiceImpl implements LedgerServiceInterface {
String[] returnArray = {"entry1","entry2","entry3"};
@Override
public List<String> getEntries(int count) {
return Arrays.asList(returnArray);
}
}
@@ -0,0 +1,10 @@
package com.baeldung;
import java.util.List;
/**
* Created by johnson on 3/9/17.
*/
public interface LedgerServiceInterface {
List<String> getEntries(int count);
}
@@ -0,0 +1,27 @@
{
"singleServerConfig": {
"idleConnectionTimeout": 10000,
"pingTimeout": 1000,
"connectTimeout": 10000,
"timeout": 3000,
"retryAttempts": 3,
"retryInterval": 1500,
"reconnectionTimeout": 3000,
"failedAttempts": 3,
"password": null,
"subscriptionsPerConnection": 5,
"clientName": null,
"address": "redis://127.0.0.1:6379",
"subscriptionConnectionMinimumIdleSize": 1,
"subscriptionConnectionPoolSize": 50,
"connectionMinimumIdleSize": 10,
"connectionPoolSize": 64,
"database": 0,
"dnsMonitoring": false,
"dnsMonitoringInterval": 5000
},
"threads": 0,
"nettyThreads": 0,
"codec": null,
"useLinuxNativeEpoll": false
}
@@ -0,0 +1,24 @@
singleServerConfig:
idleConnectionTimeout: 10000
pingTimeout: 1000
connectTimeout: 10000
timeout: 3000
retryAttempts: 3
retryInterval: 1500
reconnectionTimeout: 3000
failedAttempts: 3
password: null
subscriptionsPerConnection: 5
clientName: null
address: "redis://127.0.0.1:6379"
subscriptionConnectionMinimumIdleSize: 1
subscriptionConnectionPoolSize: 50
connectionMinimumIdleSize: 10
connectionPoolSize: 64
database: 0
dnsMonitoring: false
dnsMonitoringInterval: 5000
threads: 0
nettyThreads: 0
codec: !<org.redisson.codec.JsonJacksonCodec> {}
useLinuxNativeEpoll: false
@@ -0,0 +1,212 @@
package com.baeldung;
import org.junit.*;
import redis.clients.jedis.*;
import redis.embedded.RedisServer;
import java.io.IOException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class JedisIntegrationTest {
private Jedis jedis;
private static RedisServer redisServer;
public JedisIntegrationTest() {
jedis = new Jedis();
}
@BeforeClass
public static void setUp() throws IOException {
redisServer = new RedisServer(6379);
redisServer.start();
}
@AfterClass
public static void destroy() {
redisServer.stop();
}
@After
public void flush() {
jedis.flushAll();
}
@Test
public void givenAString_thenSaveItAsRedisStrings() {
String key = "key";
String value = "value";
jedis.set(key, value);
String value2 = jedis.get(key);
Assert.assertEquals(value, value2);
}
@Test
public void givenListElements_thenSaveThemInRedisList() {
String queue = "queue#tasks";
String taskOne = "firstTask";
String taskTwo = "secondTask";
String taskThree = "thirdTask";
jedis.lpush(queue, taskOne, taskTwo);
String taskReturnedOne = jedis.rpop(queue);
jedis.lpush(queue, taskThree);
Assert.assertEquals(taskOne, taskReturnedOne);
String taskReturnedTwo = jedis.rpop(queue);
String taskReturnedThree = jedis.rpop(queue);
Assert.assertEquals(taskTwo, taskReturnedTwo);
Assert.assertEquals(taskThree, taskReturnedThree);
String taskReturnedFour = jedis.rpop(queue);
Assert.assertNull(taskReturnedFour);
}
@Test
public void givenSetElements_thenSaveThemInRedisSet() {
String countries = "countries";
String countryOne = "Spain";
String countryTwo = "Ireland";
String countryThree = "Ireland";
jedis.sadd(countries, countryOne);
Set<String> countriesSet = jedis.smembers(countries);
Assert.assertEquals(1, countriesSet.size());
jedis.sadd(countries, countryTwo);
countriesSet = jedis.smembers(countries);
Assert.assertEquals(2, countriesSet.size());
jedis.sadd(countries, countryThree);
countriesSet = jedis.smembers(countries);
Assert.assertEquals(2, countriesSet.size());
boolean exists = jedis.sismember(countries, countryThree);
Assert.assertTrue(exists);
}
@Test
public void givenObjectFields_thenSaveThemInRedisHash() {
String key = "user#1";
String field = "name";
String value = "William";
String field2 = "job";
String value2 = "politician";
jedis.hset(key, field, value);
jedis.hset(key, field2, value2);
String value3 = jedis.hget(key, field);
Assert.assertEquals(value, value3);
Map<String, String> fields = jedis.hgetAll(key);
String value4 = fields.get(field2);
Assert.assertEquals(value2, value4);
}
@Test
public void givenARanking_thenSaveItInRedisSortedSet() {
String key = "ranking";
Map<String, Double> scores = new HashMap<>();
scores.put("PlayerOne", 3000.0);
scores.put("PlayerTwo", 1500.0);
scores.put("PlayerThree", 8200.0);
scores.keySet().forEach(player -> {
jedis.zadd(key, scores.get(player), player);
});
Set<String> players = jedis.zrevrange(key, 0, 1);
Assert.assertEquals("PlayerThree", players.iterator().next());
long rank = jedis.zrevrank(key, "PlayerOne");
Assert.assertEquals(1, rank);
}
@Test
public void givenMultipleOperationsThatNeedToBeExecutedAtomically_thenWrapThemInATransaction() {
String friendsPrefix = "friends#";
String userOneId = "4352523";
String userTwoId = "5552321";
Transaction t = jedis.multi();
t.sadd(friendsPrefix + userOneId, userTwoId);
t.sadd(friendsPrefix + userTwoId, userOneId);
t.exec();
boolean exists = jedis.sismember(friendsPrefix + userOneId, userTwoId);
Assert.assertTrue(exists);
exists = jedis.sismember(friendsPrefix + userTwoId, userOneId);
Assert.assertTrue(exists);
}
@Test
public void givenMultipleIndependentOperations_whenNetworkOptimizationIsImportant_thenWrapThemInAPipeline() {
String userOneId = "4352523";
String userTwoId = "4849888";
Pipeline p = jedis.pipelined();
p.sadd("searched#" + userOneId, "paris");
p.zadd("ranking", 126, userOneId);
p.zadd("ranking", 325, userTwoId);
Response<Boolean> pipeExists = p.sismember("searched#" + userOneId, "paris");
Response<Set<String>> pipeRanking = p.zrange("ranking", 0, -1);
p.sync();
Assert.assertTrue(pipeExists.get());
Assert.assertEquals(2, pipeRanking.get().size());
}
@Test
public void givenAPoolConfiguration_thenCreateAJedisPool() {
final JedisPoolConfig poolConfig = buildPoolConfig();
try (JedisPool jedisPool = new JedisPool(poolConfig, "localhost"); Jedis jedis = jedisPool.getResource()) {
// do simple operation to verify that the Jedis resource is working
// properly
String key = "key";
String value = "value";
jedis.set(key, value);
String value2 = jedis.get(key);
Assert.assertEquals(value, value2);
// flush Redis
jedis.flushAll();
}
}
private JedisPoolConfig buildPoolConfig() {
final JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(128);
poolConfig.setMaxIdle(128);
poolConfig.setMinIdle(16);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);
poolConfig.setMinEvictableIdleTimeMillis(Duration.ofSeconds(60).toMillis());
poolConfig.setTimeBetweenEvictionRunsMillis(Duration.ofSeconds(30).toMillis());
poolConfig.setNumTestsPerEvictionRun(3);
poolConfig.setBlockWhenExhausted(true);
return poolConfig;
}
}
@@ -0,0 +1,65 @@
package com.baeldung;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import redis.embedded.RedisServer;
import java.io.File;
import java.io.IOException;
/**
* Created by johnson on 3/9/17.
*/
public class RedissonConfigurationIntegrationTest {
private static RedisServer redisServer;
private static RedissonClient client;
@BeforeClass
public static void setUp() throws IOException {
redisServer = new RedisServer(6379);
redisServer.start();
}
@AfterClass
public static void destroy() {
redisServer.stop();
client.shutdown();
}
@Test
public void givenJavaConfig_thenRedissonConnectToRedis() {
Config config = new Config();
config.useSingleServer()
.setAddress("127.0.0.1:6379");
client = Redisson.create(config);
assert(client != null && client.getKeys().count() >= 0);
}
@Test
public void givenJSONFileConfig_thenRedissonConnectToRedis() throws IOException {
Config config = Config.fromJSON(
new File(getClass().getClassLoader().getResource(
"singleNodeConfig.json").getFile()));
client = Redisson.create(config);
assert(client != null && client.getKeys().count() >= 0);
}
@Test
public void givenYAMLFileConfig_thenRedissonConnectToRedis() throws IOException {
Config config = Config.fromYAML(
new File(getClass().getClassLoader().getResource(
"singleNodeConfig.yaml").getFile()));
client = Redisson.create(config);
assert(client != null && client.getKeys().count() >= 0);
}
}
@@ -0,0 +1,232 @@
package com.baeldung;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.redisson.Redisson;
import org.redisson.RedissonMultiLock;
import org.redisson.api.*;
import org.redisson.client.RedisClient;
import org.redisson.client.RedisConnection;
import org.redisson.client.codec.StringCodec;
import org.redisson.client.protocol.RedisCommands;
import redis.embedded.RedisServer;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class RedissonIntegrationTest {
private static RedisServer redisServer;
private static RedissonClient client;
@BeforeClass
public static void setUp() throws IOException {
redisServer = new RedisServer(6379);
redisServer.start();
client = Redisson.create();
}
@AfterClass
public static void destroy() {
redisServer.stop();
client.shutdown();
}
@Test
public void givenMultipleKeysInRedis_thenGetAllKeys() {
client.getBucket("key1").set("key1");
client.getBucket("key2").set("key2");
client.getBucket("key3").set("key3");
RKeys keys = client.getKeys();
assertTrue(keys.count() >= 3);
}
@Test
public void givenKeysWithPatternInRedis_thenGetPatternKeys() {
client.getBucket("key1").set("key1");
client.getBucket("key2").set("key2");
client.getBucket("key3").set("key3");
client.getBucket("id4").set("id4");
RKeys keys = client.getKeys();
Iterable<String> keysWithPattern
= keys.getKeysByPattern("key*");
List keyWithPatternList
= StreamSupport.stream(
keysWithPattern.spliterator(),
false).collect(Collectors.toList());
assertTrue(keyWithPatternList.size() == 3);
}
@Test
public void givenAnObject_thenSaveToRedis() {
RBucket<Ledger> bucket = client.getBucket("ledger");
Ledger ledger = new Ledger();
ledger.setName("ledger1");
bucket.set(ledger);
Ledger returnedLedger = bucket.get();
assertTrue(
returnedLedger != null
&& returnedLedger.getName().equals("ledger1"));
}
@Test
public void givenALong_thenSaveLongToRedisAndAtomicallyIncrement(){
Long value = 5L;
RAtomicLong atomicLong
= client.getAtomicLong("myAtomicLong");
atomicLong.set(value);
Long returnValue = atomicLong.incrementAndGet();
assertTrue(returnValue == 6L);
}
@Test
public void givenTopicSubscribedToAChannel_thenReceiveMessageFromChannel() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = new CompletableFuture<>();
RTopic<CustomMessage> subscribeTopic = client.getTopic("baeldung");
subscribeTopic.addListener((channel, customMessage) -> future.complete(customMessage.getMessage()));
RTopic<CustomMessage> publishTopic = client.getTopic("baeldung");
long clientsReceivedMessage
= publishTopic.publish(new CustomMessage("This is a message"));
assertEquals("This is a message", future.get());
}
@Test
public void givenAMap_thenSaveMapToRedis(){
RMap<String, Ledger> map = client.getMap("ledger");
map.put("123", new Ledger("ledger"));
assertTrue(map.get("123").getName().equals("ledger"));
}
@Test
public void givenASet_thenSaveSetToRedis(){
RSet<Ledger> ledgerSet = client.getSet("ledgerSet");
ledgerSet.add(new Ledger("ledger"));
assertTrue(ledgerSet.contains(new Ledger("ledger")));
}
@Test
public void givenAList_thenSaveListToRedis(){
RList<Ledger> ledgerList = client.getList("ledgerList");
ledgerList.add(new Ledger("ledger"));
assertTrue(ledgerList.contains(new Ledger("ledger")));
}
@Test
public void givenLockSet_thenEnsureCanUnlock(){
RLock lock = client.getLock("lock");
lock.lock();
assertTrue(lock.isLocked());
lock.unlock();
assertTrue(!lock.isLocked());
}
@Test
public void givenMultipleLocksSet_thenEnsureAllCanUnlock(){
RedissonClient clientInstance1 = Redisson.create();
RedissonClient clientInstance2 = Redisson.create();
RedissonClient clientInstance3 = Redisson.create();
RLock lock1 = clientInstance1.getLock("lock1");
RLock lock2 = clientInstance2.getLock("lock2");
RLock lock3 = clientInstance3.getLock("lock3");
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
lock.lock();
assertTrue(lock1.isLocked() && lock2.isLocked() && lock3.isLocked());
lock.unlock();
assertTrue(!(lock1.isLocked() || lock2.isLocked() || lock3.isLocked()));
}
@Test
public void givenRemoteServiceMethodRegistered_thenInvokeMethod(){
RRemoteService remoteService = client.getRemoteService();
LedgerServiceImpl ledgerServiceImpl = new LedgerServiceImpl();
remoteService.register(LedgerServiceInterface.class, ledgerServiceImpl);
LedgerServiceInterface ledgerService
= remoteService.get(LedgerServiceInterface.class);
List<String> entries = ledgerService.getEntries(10);
assertTrue(entries.size() == 3 && entries.contains("entry1"));
}
@Test
public void givenLiveObjectPersisted_thenGetLiveObject(){
RLiveObjectService service = client.getLiveObjectService();
LedgerLiveObject ledger = new LedgerLiveObject();
ledger.setName("ledger1");
ledger = service.persist(ledger);
LedgerLiveObject returnLedger
= service.get(LedgerLiveObject.class, "ledger1");
assertTrue(ledger.getName().equals(returnLedger.getName()));
}
@Test
public void givenMultipleOperations_thenDoAllAtomically(){
RBatch batch = client.createBatch();
batch.getMap("ledgerMap").fastPutAsync("1", "2");
batch.getMap("ledgerMap").putAsync("2", "5");
List<?> result = batch.execute();
RMap<String, String> map = client.getMap("ledgerMap");
assertTrue(result.size() > 0 && map.get("1").equals("2"));
}
@Test
public void givenLUAScript_thenExecuteScriptOnRedis(){
client.getBucket("foo").set("bar");
String result = client.getScript().eval(RScript.Mode.READ_ONLY,
"return redis.call('get', 'foo')", RScript.ReturnType.VALUE);
assertTrue(result.equals("bar"));
}
@Test
public void givenLowLevelRedisCommands_thenExecuteLowLevelCommandsOnRedis(){
RedisClient client = new RedisClient("localhost", 6379);
RedisConnection conn = client.connect();
conn.sync(StringCodec.INSTANCE, RedisCommands.SET, "test", 0);
String testValue = conn.sync(StringCodec.INSTANCE, RedisCommands.GET, "test");
conn.closeAsync();
client.shutdown();
assertTrue(testValue.equals("0"));
}
}
+3
View File
@@ -0,0 +1,3 @@
### Relevant articles
- [Full-text Search with Solr](http://www.baeldung.com/full-text-search-with-solr)
+30
View File
@@ -0,0 +1,30 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>solr</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>solr</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>6.4.1</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,51 @@
package com.baeldung.solr.fulltext.search.model;
import org.apache.solr.client.solrj.beans.Field;
public class Item {
@Field
private String id;
@Field
private String description;
@Field
private String category;
@Field
private float price;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
@@ -0,0 +1,15 @@
package com.baeldung.solr.fulltext.search.service;
import java.io.IOException;
import org.apache.solr.client.solrj.SolrServerException;
import com.baeldung.solr.fulltext.search.model.Item;
public interface ItemSearchService {
public void index(String id, String description, String category, float price) throws SolrServerException, IOException;
public void indexBean(Item item) throws IOException, SolrServerException;
}
@@ -0,0 +1,34 @@
package com.baeldung.solr.fulltext.search.service;
import java.io.IOException;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.common.SolrInputDocument;
import com.baeldung.solr.fulltext.search.model.Item;
public class ItemSearchServiceImpl implements ItemSearchService {
private final SolrClient solrClient;
public ItemSearchServiceImpl(SolrClient solrClient) {
this.solrClient = solrClient;
}
public void index(String id, String description, String category, float price) throws SolrServerException, IOException {
SolrInputDocument doc = new SolrInputDocument();
doc.addField("id", id);
doc.addField("description", description);
doc.addField("category", category);
doc.addField("price", price);
solrClient.add(doc);
solrClient.commit();
}
public void indexBean(Item item) throws IOException, SolrServerException {
solrClient.addBean(item);
solrClient.commit();
}
}
@@ -0,0 +1,374 @@
package com.baeldung.solr.fulltext.search.service;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.List;
import java.util.Map;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.FacetField.Count;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.RangeFacet;
import org.apache.solr.client.solrj.response.SpellCheckResponse;
import org.apache.solr.client.solrj.response.SpellCheckResponse.Suggestion;
import org.apache.solr.client.solrj.response.SuggesterResponse;
import org.apache.solr.common.SolrDocument;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.baeldung.solr.fulltext.search.model.Item;
public class ItemSearchServiceLiveTest {
private static SolrClient solrClient;
private static ItemSearchService itemSearchService;
private static final String solrUrl = "http://localhost:8983/solr/item";
@BeforeClass
public static void initBeans() throws Exception {
solrClient = new HttpSolrClient.Builder(solrUrl).build();
itemSearchService = new ItemSearchServiceImpl(solrClient);
solrClient.commit();
}
@Before
public void clearSolrData() throws Exception {
solrClient.deleteByQuery("*:*");
}
@Test
public void whenIndexing_thenAvailableOnRetrieval() throws Exception {
itemSearchService.index("hm0001", "Washing Machine", "Home Appliances", 450f);
final SolrDocument indexedDoc = solrClient.getById("hm0001");
assertEquals("hm0001", indexedDoc.get("id"));
}
@Test
public void whenIndexingBean_thenAvailableOnRetrieval() throws Exception {
Item item = new Item();
item.setId("hm0002");
item.setCategory("Televisions");
item.setDescription("LED TV 32");
item.setPrice(500);
itemSearchService.indexBean(item);
}
@Test
public void whenSearchingByBasicQuery_thenAllMatchingItemsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
itemSearchService.index("hm0003", "LED TV 32", "Brand1 Home Appliances", 450f);
SolrQuery query = new SolrQuery();
query.setQuery("brand1");
query.setStart(0);
query.setRows(10);
QueryResponse response = solrClient.query(query);
List<Item> items = response.getBeans(Item.class);
assertEquals(3, items.size());
}
@Test
public void whenSearchingWithWildCard_thenAllMatchingItemsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
itemSearchService.index("hm0003", "LED TV 32", "Brand1 Home Appliances", 450f);
SolrQuery query = new SolrQuery();
query.setQuery("*rand?");
QueryResponse response = solrClient.query(query);
List<Item> items = response.getBeans(Item.class);
assertEquals(3, items.size());
}
@Test
public void whenSearchingWithLogicalOperators_thenAllMatchingItemsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
itemSearchService.index("hm0003", "Brand2 LED TV 32", "Washing Appliances", 450f);
SolrQuery query = new SolrQuery();
query.setQuery("brand1 AND (Washing OR Refrigerator)");
QueryResponse response = solrClient.query(query);
List<Item> items = response.getBeans(Item.class);
assertEquals(2, items.size());
}
@Test
public void whenSearchingWithFields_thenAllMatchingItemsShouldAvialble() throws Exception {
itemSearchService.index("0001", "Brand1 Washing Machine", "Home Appliances", 450f);
itemSearchService.index("0002", "Brand1 Refrigerator", "Home Appliances", 450f);
itemSearchService.index("0003", "Brand2 LED TV 32", "Brand1 Washing Home Appliances", 450f);
SolrQuery query = new SolrQuery();
query.setQuery("description:Brand* AND category:*Washing*");
QueryResponse response = solrClient.query(query);
List<Item> items = response.getBeans(Item.class);
assertEquals(1, items.size());
}
@Test
public void whenSearchingWithPhrase_thenAllMatchingItemsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
SolrQuery query = new SolrQuery();
query.setQuery("washing MachIne");
QueryResponse response = solrClient.query(query);
List<Item> items = response.getBeans(Item.class);
assertEquals(2, items.size());
}
@Test
public void whenSearchingWithRealPhrase_thenAllMatchingItemsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
SolrQuery query = new SolrQuery();
query.setQuery("\"washing machine\"");
QueryResponse response = solrClient.query(query);
List<Item> items = response.getBeans(Item.class);
assertEquals(1, items.size());
}
@Test
public void whenSearchingPhraseWithProximity_thenAllMatchingItemsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
SolrQuery query = new SolrQuery();
query.setQuery("\"Washing equipment\"~2");
QueryResponse response = solrClient.query(query);
List<Item> items = response.getBeans(Item.class);
assertEquals(1, items.size());
}
@Test
public void whenSearchingWithPriceRange_thenAllMatchingItemsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Home Appliances", 200f);
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
SolrQuery query = new SolrQuery();
query.setQuery("price:[100 TO 300]");
QueryResponse response = solrClient.query(query);
List<Item> items = response.getBeans(Item.class);
assertEquals(3, items.size());
}
@Test
public void whenSearchingWithPriceRangeInclusiveExclusive_thenAllMatchingItemsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Home Appliances", 200f);
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
SolrQuery query = new SolrQuery();
query.setQuery("price:{100 TO 300]");
QueryResponse response = solrClient.query(query);
List<Item> items = response.getBeans(Item.class);
assertEquals(2, items.size());
}
@Test
public void whenSearchingWithFilterQuery_thenAllMatchingItemsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f);
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing tools and equipment ", 250f);
SolrQuery query = new SolrQuery();
query.setQuery("price:[100 TO 300]");
query.addFilterQuery("description:Brand1", "category:Home Appliances");
QueryResponse response = solrClient.query(query);
List<Item> items = response.getBeans(Item.class);
assertEquals(2, items.size());
}
@Test
public void whenSearchingWithFacetFields_thenAllMatchingFacetsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 300f);
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 200f);
itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f);
SolrQuery query = new SolrQuery();
query.setQuery("*:*");
query.addFacetField("category");
QueryResponse response = solrClient.query(query);
List<Count> facetResults = response.getFacetField("category").getValues();
assertEquals(2, facetResults.size());
for (Count count : facetResults) {
if ("categorya".equalsIgnoreCase(count.getName())) {
assertEquals(2, count.getCount());
} else if ("categoryb".equalsIgnoreCase(count.getName())) {
assertEquals(2, count.getCount());
} else {
fail("unexpected category");
}
}
}
@Test
public void whenSearchingWithFacetQuery_thenAllMatchingFacetsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 300f);
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 200f);
itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f);
SolrQuery query = new SolrQuery();
query.setQuery("*:*");
query.addFacetQuery("Washing OR Refrigerator");
query.addFacetQuery("Brand2");
QueryResponse response = solrClient.query(query);
Map<String, Integer> facetQueryMap = response.getFacetQuery();
assertEquals(2, facetQueryMap.size());
for (Map.Entry<String, Integer> entry : facetQueryMap.entrySet()) {
String facetQuery = entry.getKey();
if ("Washing OR Refrigerator".equals(facetQuery)) {
assertEquals(Integer.valueOf(2), entry.getValue());
} else if ("Brand2".equals(facetQuery)) {
assertEquals(Integer.valueOf(2), entry.getValue());
} else {
fail("unexpected query");
}
}
}
@Test
public void whenSearchingWithFacetRange_thenAllMatchingFacetsShouldAvialble() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 125f);
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 150f);
itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f);
SolrQuery query = new SolrQuery();
query.setQuery("*:*");
query.addNumericRangeFacet("price", 100, 275, 25);
QueryResponse response = solrClient.query(query);
List<RangeFacet> rangeFacets = response.getFacetRanges().get(0).getCounts();
assertEquals(7, rangeFacets.size());
}
@Test
public void whenSearchingWithHitHighlighting_thenKeywordsShouldBeHighlighted() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f);
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing equipments", 250f);
SolrQuery query = new SolrQuery();
query.setQuery("Appliances");
query.setHighlight(true);
query.addHighlightField("category");
query.setHighlightSimplePre("<strong>");
query.setHighlightSimplePost("</strong>");
QueryResponse response = solrClient.query(query);
Map<String, Map<String, List<String>>> hitHighlightedMap = response.getHighlighting();
Map<String, List<String>> highlightedFieldMap = hitHighlightedMap.get("hm0001");
List<String> highlightedList = highlightedFieldMap.get("category");
String highLightedText = highlightedList.get(0);
assertEquals("Home <strong>Appliances</strong>", highLightedText);
}
@Test
public void whenSearchingWithKeywordWithMistake_thenSpellingSuggestionsShouldBeReturned() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f);
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing equipments", 250f);
SolrQuery query = new SolrQuery();
query.setQuery("hme");
query.set("spellcheck", "on");
QueryResponse response = solrClient.query(query);
SpellCheckResponse spellCheckResponse = response.getSpellCheckResponse();
assertEquals(false, spellCheckResponse.isCorrectlySpelled());
Suggestion suggestion = spellCheckResponse.getSuggestions().get(0);
assertEquals("hme", suggestion.getToken());
List<String> alternatives = suggestion.getAlternatives();
String alternative = alternatives.get(0);
assertEquals("home", alternative);
}
@Test
public void whenSearchingWithIncompleteKeyword_thenKeywordSuggestionsShouldBeReturned() throws Exception {
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f);
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Home washing equipments", 250f);
SolrQuery query = new SolrQuery();
query.setRequestHandler("/suggest");
query.set("suggest", "true");
query.set("suggest.build", "true");
query.set("suggest.dictionary", "mySuggester");
query.set("suggest.q", "Hom");
QueryResponse response = solrClient.query(query);
SuggesterResponse suggesterResponse = response.getSuggesterResponse();
Map<String, List<String>> suggestedTerms = suggesterResponse.getSuggestedTerms();
List<String> suggestions = suggestedTerms.get("mySuggester");
assertEquals(2, suggestions.size());
for (String term : suggestions) {
if (!"Home Appliances".equals(term) && !"Home washing equipments".equals(term)) {
fail("Unexpected suggestions");
}
}
}
}
@@ -0,0 +1,16 @@
## Spring Data Cassandra
### Relevant Articles:
- [Introduction to Spring Data Cassandra](http://www.baeldung.com/spring-data-cassandra-tutorial)
- [Using the CassandraTemplate from Spring Data](http://www.baeldung.com/spring-data-cassandratemplate-cqltemplate)
### Build the Project with Tests Running
```
mvn clean install
```
### Run Tests Directly
```
mvn test
```
@@ -0,0 +1,125 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>spring-data-cassandra</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-data-cassandra</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.springframework.version>4.3.4.RELEASE</org.springframework.version>
<org.springframework.data.version>1.3.2.RELEASE</org.springframework.data.version>
<cassandra-driver-core.version>2.1.5</cassandra-driver-core.version>
<cassandra-unit-spring.version>2.1.9.2</cassandra-unit-spring.version>
<cassandra-unit-shaded.version>2.1.9.2</cassandra-unit-shaded.version>
<hector-core.version>2.0-0</hector-core.version>
<guava.version>19.0</guava.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra</artifactId>
<version>${org.springframework.data.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.cassandraunit</groupId>
<artifactId>cassandra-unit-spring</artifactId>
<version>${cassandra-unit-spring.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.cassandraunit</groupId>
<artifactId>cassandra-unit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.cassandraunit</groupId>
<artifactId>cassandra-unit-shaded</artifactId>
<version>${cassandra-unit-shaded.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hectorclient</groupId>
<artifactId>hector-core</artifactId>
<version>${hector-core.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>${cassandra-driver-core.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
<profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*LiveTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
@@ -0,0 +1,45 @@
package org.baeldung.spring.data.cassandra.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.cassandra.config.CassandraClusterFactoryBean;
import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
@Configuration
@PropertySource(value = { "classpath:cassandra.properties" })
@EnableCassandraRepositories(basePackages = "org.baeldung.spring.data.cassandra.repository")
public class CassandraConfig extends AbstractCassandraConfiguration {
private static final Log LOGGER = LogFactory.getLog(CassandraConfig.class);
@Autowired
private Environment environment;
@Override
protected String getKeyspaceName() {
return environment.getProperty("cassandra.keyspace");
}
@Override
@Bean
public CassandraClusterFactoryBean cluster() {
final CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
cluster.setContactPoints(environment.getProperty("cassandra.contactpoints"));
cluster.setPort(Integer.parseInt(environment.getProperty("cassandra.port")));
LOGGER.info("Cluster created with contact points [" + environment.getProperty("cassandra.contactpoints") + "] " + "& port [" + Integer.parseInt(environment.getProperty("cassandra.port")) + "].");
return cluster;
}
@Override
@Bean
public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
return new BasicCassandraMappingContext();
}
}
@@ -0,0 +1,67 @@
package org.baeldung.spring.data.cassandra.model;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.springframework.cassandra.core.Ordering;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;
@Table
public class Book {
@PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.DESCENDING)
private UUID id;
@PrimaryKeyColumn(name = "title", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
private String title;
@PrimaryKeyColumn(name = "publisher", ordinal = 2, type = PrimaryKeyType.PARTITIONED)
private String publisher;
@Column
private Set<String> tags = new HashSet<>();
public Book(final UUID id, final String title, final String publisher, final Set<String> tags) {
this.id = id;
this.title = title;
this.publisher = publisher;
this.tags.addAll(tags);
}
public UUID getId() {
return id;
}
public String getTitle() {
return title;
}
public String getPublisher() {
return publisher;
}
public Set getTags() {
return tags;
}
public void setId(final UUID id) {
this.id = id;
}
public void setTitle(final String title) {
this.title = title;
}
public void setPublisher(final String publisher) {
this.publisher = publisher;
}
public void setTags(final Set<String> tags) {
this.tags = tags;
}
}
@@ -0,0 +1,14 @@
package org.baeldung.spring.data.cassandra.repository;
import org.baeldung.spring.data.cassandra.model.Book;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.cassandra.repository.Query;
import org.springframework.stereotype.Repository;
@Repository
public interface BookRepository extends CassandraRepository<Book> {
@Query("select * from book where title = ?0 and publisher=?1")
Iterable<Book> findByTitleAndPublisher(String title, String publisher);
}
@@ -0,0 +1,3 @@
cassandra.contactpoints=127.0.0.1
cassandra.port=9142
cassandra.keyspace=testKeySpace
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>web - %date [%thread] %-5level %logger{36} - %message%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

@@ -0,0 +1,121 @@
package org.baeldung.spring.data.cassandra.repository;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import java.io.IOException;
import java.util.HashMap;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.thrift.transport.TTransportException;
import org.baeldung.spring.data.cassandra.config.CassandraConfig;
import org.baeldung.spring.data.cassandra.model.Book;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cassandra.core.cql.CqlIdentifier;
import org.springframework.data.cassandra.core.CassandraAdminOperations;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.utils.UUIDs;
import com.google.common.collect.ImmutableSet;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CassandraConfig.class)
public class BookRepositoryIntegrationTest {
private static final Log LOGGER = LogFactory.getLog(BookRepositoryIntegrationTest.class);
public static final String KEYSPACE_CREATION_QUERY = "CREATE KEYSPACE IF NOT EXISTS testKeySpace WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };";
public static final String KEYSPACE_ACTIVATE_QUERY = "USE testKeySpace;";
public static final String DATA_TABLE_NAME = "book";
@Autowired
private BookRepository bookRepository;
@Autowired
private CassandraAdminOperations adminTemplate;
//
@BeforeClass
public static void startCassandraEmbedded() throws InterruptedException, TTransportException, ConfigurationException, IOException {
EmbeddedCassandraServerHelper.startEmbeddedCassandra();
final Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withPort(9142).build();
LOGGER.info("Server Started at 127.0.0.1:9142... ");
final Session session = cluster.connect();
session.execute(KEYSPACE_CREATION_QUERY);
session.execute(KEYSPACE_ACTIVATE_QUERY);
LOGGER.info("KeySpace created and activated.");
Thread.sleep(5000);
}
@Before
public void createTable() throws InterruptedException, TTransportException, ConfigurationException, IOException {
adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap<String, Object>());
}
@Test
public void whenSavingBook_thenAvailableOnRetrieval() {
final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
bookRepository.save(ImmutableSet.of(javaBook));
final Iterable<Book> books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
assertEquals(javaBook.getId(), books.iterator().next().getId());
}
@Test
public void whenUpdatingBooks_thenAvailableOnRetrieval() {
final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
bookRepository.save(ImmutableSet.of(javaBook));
final Iterable<Book> books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
javaBook.setTitle("Head First Java Second Edition");
bookRepository.save(ImmutableSet.of(javaBook));
final Iterable<Book> updateBooks = bookRepository.findByTitleAndPublisher("Head First Java Second Edition", "O'Reilly Media");
assertEquals(javaBook.getTitle(), updateBooks.iterator().next().getTitle());
}
@Test(expected = java.util.NoSuchElementException.class)
public void whenDeletingExistingBooks_thenNotAvailableOnRetrieval() {
final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
bookRepository.save(ImmutableSet.of(javaBook));
bookRepository.delete(javaBook);
final Iterable<Book> books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
assertNotEquals(javaBook.getId(), books.iterator().next().getId());
}
@Test
public void whenSavingBooks_thenAllShouldAvailableOnRetrieval() {
final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
final Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
bookRepository.save(ImmutableSet.of(javaBook));
bookRepository.save(ImmutableSet.of(dPatternBook));
final Iterable<Book> books = bookRepository.findAll();
int bookCount = 0;
for (final Book book : books) {
bookCount++;
}
assertEquals(bookCount, 2);
}
@After
public void dropTable() {
adminTemplate.dropTable(CqlIdentifier.cqlId(DATA_TABLE_NAME));
}
@AfterClass
public static void stopCassandraEmbedded() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
}
@@ -0,0 +1,154 @@
package org.baeldung.spring.data.cassandra.repository;
import static junit.framework.TestCase.assertNull;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.thrift.transport.TTransportException;
import org.baeldung.spring.data.cassandra.config.CassandraConfig;
import org.baeldung.spring.data.cassandra.model.Book;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cassandra.core.cql.CqlIdentifier;
import org.springframework.data.cassandra.core.CassandraAdminOperations;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
import com.datastax.driver.core.utils.UUIDs;
import com.google.common.collect.ImmutableSet;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CassandraConfig.class)
public class CassandraTemplateIntegrationTest {
private static final Log LOGGER = LogFactory.getLog(CassandraTemplateIntegrationTest.class);
public static final String KEYSPACE_CREATION_QUERY = "CREATE KEYSPACE IF NOT EXISTS testKeySpace " + "WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };";
public static final String KEYSPACE_ACTIVATE_QUERY = "USE testKeySpace;";
public static final String DATA_TABLE_NAME = "book";
@Autowired
private CassandraAdminOperations adminTemplate;
@Autowired
private CassandraOperations cassandraTemplate;
//
@BeforeClass
public static void startCassandraEmbedded() throws InterruptedException, TTransportException, ConfigurationException, IOException {
EmbeddedCassandraServerHelper.startEmbeddedCassandra();
final Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withPort(9142).build();
LOGGER.info("Server Started at 127.0.0.1:9142... ");
final Session session = cluster.connect();
session.execute(KEYSPACE_CREATION_QUERY);
session.execute(KEYSPACE_ACTIVATE_QUERY);
LOGGER.info("KeySpace created and activated.");
Thread.sleep(5000);
}
@Before
public void createTable() throws InterruptedException, TTransportException, ConfigurationException, IOException {
adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap<String, Object>());
}
@Test
public void whenSavingBook_thenAvailableOnRetrieval() {
final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
cassandraTemplate.insert(javaBook);
final Select select = QueryBuilder.select().from("book").where(QueryBuilder.eq("title", "Head First Java")).and(QueryBuilder.eq("publisher", "O'Reilly Media")).limit(10);
final Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
assertEquals(javaBook.getId(), retrievedBook.getId());
}
@Test
public void whenSavingBooks_thenAllAvailableOnRetrieval() {
final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
final Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
final List<Book> bookList = new ArrayList<>();
bookList.add(javaBook);
bookList.add(dPatternBook);
cassandraTemplate.insert(bookList);
final Select select = QueryBuilder.select().from("book").limit(10);
final List<Book> retrievedBooks = cassandraTemplate.select(select, Book.class);
assertThat(retrievedBooks.size(), is(2));
assertEquals(javaBook.getId(), retrievedBooks.get(0).getId());
assertEquals(dPatternBook.getId(), retrievedBooks.get(1).getId());
}
@Test
public void whenUpdatingBook_thenShouldUpdatedOnRetrieval() {
final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
cassandraTemplate.insert(javaBook);
final Select select = QueryBuilder.select().from("book").limit(10);
final Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
retrievedBook.setTags(ImmutableSet.of("Java", "Programming"));
cassandraTemplate.update(retrievedBook);
final Book retrievedUpdatedBook = cassandraTemplate.selectOne(select, Book.class);
assertEquals(retrievedBook.getTags(), retrievedUpdatedBook.getTags());
}
@Test
public void whenDeletingASelectedBook_thenNotAvailableOnRetrieval() throws InterruptedException {
final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "OReilly Media", ImmutableSet.of("Computer", "Software"));
cassandraTemplate.insert(javaBook);
cassandraTemplate.delete(javaBook);
final Select select = QueryBuilder.select().from("book").limit(10);
final Book retrievedUpdatedBook = cassandraTemplate.selectOne(select, Book.class);
assertNull(retrievedUpdatedBook);
}
@Test
public void whenDeletingAllBooks_thenNotAvailableOnRetrieval() {
final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
final Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
cassandraTemplate.insert(javaBook);
cassandraTemplate.insert(dPatternBook);
cassandraTemplate.deleteAll(Book.class);
final Select select = QueryBuilder.select().from("book").limit(10);
final Book retrievedUpdatedBook = cassandraTemplate.selectOne(select, Book.class);
assertNull(retrievedUpdatedBook);
}
@Test
public void whenAddingBooks_thenCountShouldBeCorrectOnRetrieval() {
final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
final Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
cassandraTemplate.insert(javaBook);
cassandraTemplate.insert(dPatternBook);
final long bookCount = cassandraTemplate.count(Book.class);
assertEquals(2, bookCount);
}
@After
public void dropTable() {
adminTemplate.dropTable(CqlIdentifier.cqlId(DATA_TABLE_NAME));
}
@AfterClass
public static void stopCassandraEmbedded() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
}
@@ -0,0 +1,124 @@
package org.baeldung.spring.data.cassandra.repository;
import static junit.framework.TestCase.assertEquals;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.thrift.transport.TTransportException;
import org.baeldung.spring.data.cassandra.config.CassandraConfig;
import org.baeldung.spring.data.cassandra.model.Book;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cassandra.core.cql.CqlIdentifier;
import org.springframework.data.cassandra.core.CassandraAdminOperations;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.querybuilder.Insert;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
import com.datastax.driver.core.utils.UUIDs;
import com.google.common.collect.ImmutableSet;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = CassandraConfig.class)
public class CqlQueriesIntegrationTest {
private static final Log LOGGER = LogFactory.getLog(CqlQueriesIntegrationTest.class);
public static final String KEYSPACE_CREATION_QUERY = "CREATE KEYSPACE IF NOT EXISTS testKeySpace " + "WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };";
public static final String KEYSPACE_ACTIVATE_QUERY = "USE testKeySpace;";
public static final String DATA_TABLE_NAME = "book";
@Autowired
private CassandraAdminOperations adminTemplate;
@Autowired
private CassandraOperations cassandraTemplate;
//
@BeforeClass
public static void startCassandraEmbedded() throws InterruptedException, TTransportException, ConfigurationException, IOException {
EmbeddedCassandraServerHelper.startEmbeddedCassandra(25000);
final Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withPort(9142).build();
LOGGER.info("Server Started at 127.0.0.1:9142... ");
final Session session = cluster.connect();
session.execute(KEYSPACE_CREATION_QUERY);
session.execute(KEYSPACE_ACTIVATE_QUERY);
LOGGER.info("KeySpace created and activated.");
Thread.sleep(5000);
}
@Before
public void createTable() throws InterruptedException, TTransportException, ConfigurationException, IOException {
adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap<String, Object>());
}
@Test
public void whenSavingBook_thenAvailableOnRetrieval_usingQueryBuilder() {
final UUID uuid = UUIDs.timeBased();
final Insert insert = QueryBuilder.insertInto(DATA_TABLE_NAME).value("id", uuid).value("title", "Head First Java").value("publisher", "OReilly Media").value("tags", ImmutableSet.of("Software"));
cassandraTemplate.execute(insert);
final Select select = QueryBuilder.select().from("book").limit(10);
final Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
assertEquals(uuid, retrievedBook.getId());
}
@Test
public void whenSavingBook_thenAvailableOnRetrieval_usingCQLStatements() {
final UUID uuid = UUIDs.timeBased();
final String insertCql = "insert into book (id, title, publisher, tags) values " + "(" + uuid + ", 'Head First Java', 'OReilly Media', {'Software'})";
cassandraTemplate.execute(insertCql);
final Select select = QueryBuilder.select().from("book").limit(10);
final Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
assertEquals(uuid, retrievedBook.getId());
}
@Test
public void whenSavingBook_thenAvailableOnRetrieval_usingPreparedStatements() throws InterruptedException {
final UUID uuid = UUIDs.timeBased();
final String insertPreparedCql = "insert into book (id, title, publisher, tags) values (?, ?, ?, ?)";
final List<Object> singleBookArgsList = new ArrayList<>();
final List<List<?>> bookList = new ArrayList<>();
singleBookArgsList.add(uuid);
singleBookArgsList.add("Head First Java");
singleBookArgsList.add("OReilly Media");
singleBookArgsList.add(ImmutableSet.of("Software"));
bookList.add(singleBookArgsList);
cassandraTemplate.ingest(insertPreparedCql, bookList);
// This may not be required, just added to avoid any transient issues
Thread.sleep(5000);
final Select select = QueryBuilder.select().from("book");
final Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
assertEquals(uuid, retrievedBook.getId());
}
@After
public void dropTable() {
adminTemplate.dropTable(CqlIdentifier.cqlId(DATA_TABLE_NAME));
}
@AfterClass
public static void stopCassandraEmbedded() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
}
@@ -0,0 +1,4 @@
/target/
.settings/
.classpath
.project
@@ -0,0 +1,2 @@
### Relevant Articles:
- [DynamoDB in a Spring Boot Application Using Spring Data](http://www.baeldung.com/spring-data-dynamodb)
@@ -0,0 +1,165 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>spring-boot-dynamodb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spring Boot Actuator</name>
<description>This is simple boot application for Spring boot actuator test</description>
<parent>
<artifactId>parent-boot-5</artifactId>
<groupId>com.baeldung</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-5</relativePath>
</parent>
<properties>
<!-- The main class to start by executing java -jar -->
<start-class>com.baeldung.Application</start-class>
<spring.version>4.3.4.RELEASE</spring.version>
<httpclient.version>4.5.2</httpclient.version>
<spring-data-dynamodb.version>4.4.1</spring-data-dynamodb.version>
<aws-java-sdk-dynamodb.version>1.11.64</aws-java-sdk-dynamodb.version>
<bootstrap.version>3.3.7-1</bootstrap.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>Hopper-SR10</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>${bootstrap.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
<version>${aws-java-sdk-dynamodb.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.derjust</groupId>
<artifactId>spring-data-dynamodb</artifactId>
<version>${spring-data-dynamodb.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
</dependencies>
<build>
<finalName>spring-boot</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
@@ -0,0 +1,13 @@
package com.baeldung;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(basePackages = { "com.baeldung" })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@@ -0,0 +1,40 @@
package com.baeldung.spring.data.dynamodb.config;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
@Configuration
@EnableDynamoDBRepositories(basePackages = "com.baeldung.spring.data.dynamodb.repositories")
public class DynamoDBConfig {
@Value("${amazon.dynamodb.endpoint}")
private String amazonDynamoDBEndpoint;
@Value("${amazon.aws.accesskey}")
private String amazonAWSAccessKey;
@Value("${amazon.aws.secretkey}")
private String amazonAWSSecretKey;
@Bean
public AmazonDynamoDB amazonDynamoDB() {
AmazonDynamoDB amazonDynamoDB = new AmazonDynamoDBClient(amazonAWSCredentials());
if (!StringUtils.isEmpty(amazonDynamoDBEndpoint)) {
amazonDynamoDB.setEndpoint(amazonDynamoDBEndpoint);
}
return amazonDynamoDB;
}
@Bean
public AWSCredentials amazonAWSCredentials() {
return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey);
}
}
@@ -0,0 +1,49 @@
package com.baeldung.spring.data.dynamodb.model;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
@DynamoDBTable(tableName = "ProductInfo")
public class ProductInfo {
private String id;
private String msrp;
private String cost;
public ProductInfo() {
}
public ProductInfo(String cost, String msrp) {
this.msrp = msrp;
this.cost = cost;
}
@DynamoDBHashKey
@DynamoDBAutoGeneratedKey
public String getId() {
return id;
}
@DynamoDBAttribute
public String getMsrp() {
return msrp;
}
@DynamoDBAttribute
public String getCost() {
return cost;
}
public void setId(String id) {
this.id = id;
}
public void setMsrp(String msrp) {
this.msrp = msrp;
}
public void setCost(String cost) {
this.cost = cost;
}
}
@@ -0,0 +1,12 @@
package com.baeldung.spring.data.dynamodb.repositories;
import com.baeldung.spring.data.dynamodb.model.ProductInfo;
import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
@EnableScan
public interface ProductInfoRepository extends CrudRepository<ProductInfo, String> {
List<ProductInfo> findById(String id);
}
@@ -0,0 +1,32 @@
server.port=8080
server.contextPath=/springbootapp
management.port=8081
management.address=127.0.0.1
endpoints.shutdown.enabled=true
endpoints.jmx.domain=Spring Sample Application
endpoints.jmx.uniqueNames=true
spring.jmx.enabled=true
endpoints.jmx.enabled=true
## for pretty printing of json when endpoints accessed over HTTP
http.mappers.jsonPrettyPrint=true
## Configuring info endpoint
info.app.name=Spring Sample Application
info.app.description=This is my first spring boot application G1
info.app.version=1.0.0
## Spring Security Configurations
security.user.name=admin1
security.user.password=secret1
management.security.role=SUPERUSER
logging.level.org.springframework=INFO
#AWS Keys
amazon.dynamodb.endpoint=http://localhost:8000/
amazon.aws.accesskey=test1
amazon.aws.secretkey=test1
@@ -0,0 +1,6 @@
spring.output.ansi.enabled=never
server.port=7070
# Security
security.user.name=admin
security.user.password=password
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>web - %date [%thread] %-5level %logger{36} - %message%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -0,0 +1,19 @@
<html>
<head>
<title>WebJars Demo</title>
<link rel="stylesheet" href="/webjars/bootstrap/3.3.4/css/bootstrap.min.css" />
</head>
<body>
<div class="container"><br/>
<div class="alert alert-success">
<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
<strong>Success!</strong> It is working as we expected.
</div>
</div>
<script src="/webjars/jquery/2.1.4/jquery.min.js"></script>
<script src="/webjars/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</body>
</html>
@@ -0,0 +1,75 @@
package com.baeldung.spring.data.dynamodb.repository;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ResourceInUseException;
import com.baeldung.Application;
import com.baeldung.spring.data.dynamodb.model.ProductInfo;
import com.baeldung.spring.data.dynamodb.repositories.ProductInfoRepository;
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.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import java.util.List;
import static org.junit.Assert.assertTrue;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
@ActiveProfiles("local")
@TestPropertySource(properties = { "amazon.dynamodb.endpoint=http://localhost:8000/", "amazon.aws.accesskey=test1", "amazon.aws.secretkey=test231" })
public class ProductInfoRepositoryIntegrationTest {
private DynamoDBMapper dynamoDBMapper;
@Autowired
private AmazonDynamoDB amazonDynamoDB;
@Autowired
ProductInfoRepository repository;
private static final String EXPECTED_COST = "20";
private static final String EXPECTED_PRICE = "50";
@Before
@Ignore // TODO Remove Ignore annotations when running locally with Local DynamoDB instance
public void setup() throws Exception {
try {
dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB);
CreateTableRequest tableRequest = dynamoDBMapper.generateCreateTableRequest(ProductInfo.class);
tableRequest.setProvisionedThroughput(new ProvisionedThroughput(1L, 1L));
amazonDynamoDB.createTable(tableRequest);
} catch (ResourceInUseException e) {
// Do nothing, table already created
}
// TODO How to handle different environments. i.e. AVOID deleting all entries in ProductInfoion table
dynamoDBMapper.batchDelete((List<ProductInfo>) repository.findAll());
}
@Test
@Ignore // TODO Remove Ignore annotations when running locally with Local DynamoDB instance
public void givenItemWithExpectedCost_whenRunFindAll_thenItemIsFound() {
ProductInfo productInfo = new ProductInfo(EXPECTED_COST, EXPECTED_PRICE);
repository.save(productInfo);
List<ProductInfo> result = (List<ProductInfo>) repository.findAll();
assertTrue("Not empty", result.size() > 0);
assertTrue("Contains item with expected cost", result.get(0).getCost().equals(EXPECTED_COST));
}
}
@@ -0,0 +1,7 @@
spring.mail.host=localhost
spring.mail.port=8025
spring.mail.properties.mail.smtp.auth=false
amazon.dynamodb.endpoint=http://localhost:8000/
amazon.aws.accesskey=key
amazon.aws.secretkey=key2
@@ -0,0 +1,2 @@
spring.profiles.active=exception
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
@@ -0,0 +1,6 @@
# Security
security.user.name=admin
security.user.password=password
spring.dao.exceptiontranslation.enabled=false
spring.profiles.active=exception
@@ -0,0 +1,3 @@
### Relevant articles
- [A Guide to GemFire with Spring Data](http://www.baeldung.com/spring-data-gemfire)
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>spring-data-gemfire</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<properties>
<spring-data-gemfire-version>1.7.4.RELEASE</spring-data-gemfire-version>
<gemfire-version>7.0.1</gemfire-version>
<google-collections-version>1.0</google-collections-version>
<spring-context-version>4.3.0.RELEASE</spring-context-version>
<spring-test-version>4.3.0.RELEASE</spring-test-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-gemfire</artifactId>
<version>${spring-data-gemfire-version}</version>
</dependency>
<dependency>
<groupId>com.gemstone.gemfire</groupId>
<artifactId>gemfire</artifactId>
<version>${gemfire-version}</version>
</dependency>
<!-- Google List API -->
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>${google-collections-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-context-version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-test-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/libs-snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>gemstone</id>
<url>http://dist.gemstone.com.s3.amazonaws.com/maven/release/</url>
</repository>
</repositories>
</project>
@@ -0,0 +1,16 @@
package com.baeldung.spring.data.gemfire.function;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.gemfire.function.annotation.FunctionId;
import org.springframework.data.gemfire.function.annotation.OnRegion;
import org.springframework.data.gemfire.function.annotation.RegionData;
import java.util.Map;
import java.util.Set;
@OnRegion(region="employee")
public interface FunctionExecution {
@FunctionId("greeting")
public void execute(String message);
}
@@ -0,0 +1,18 @@
package com.baeldung.spring.data.gemfire.function;
import org.springframework.data.gemfire.function.annotation.GemfireFunction;
import org.springframework.stereotype.Component;
@Component
public class FunctionImpl {
@GemfireFunction
public void greeting(String message){
System.out.println("Message "+message);
}
@GemfireFunction
public String sayHello(String message){
return "Hello "+message;
}
}
@@ -0,0 +1,65 @@
package com.baeldung.spring.data.gemfire.function;
import com.baeldung.spring.data.gemfire.model.Employee;
import com.baeldung.spring.data.gemfire.repository.EmployeeRepository;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.GemFireCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.LocalRegionFactoryBean;
import org.springframework.data.gemfire.function.config.EnableGemfireFunctionExecutions;
import org.springframework.data.gemfire.function.config.EnableGemfireFunctions;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
import java.util.Properties;
@Configuration
@ComponentScan
@EnableGemfireRepositories(basePackages = "com.baeldung.spring.data.gemfire.repository")
@EnableGemfireFunctions
@EnableGemfireFunctionExecutions(basePackages = "com.baeldung.spring.data.gemfire.function")
public class GemfireConfiguration {
@Autowired
EmployeeRepository employeeRepository;
@Autowired
FunctionExecution functionExecution;
@Bean
Properties gemfireProperties() {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", "SpringDataGemFireApplication");
gemfireProperties.setProperty("mcast-port", "0");
gemfireProperties.setProperty("log-level", "config");
return gemfireProperties;
}
@Bean
@Autowired
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setProperties(gemfireProperties());
return gemfireCache;
}
@Bean(name="employee")
@Autowired
LocalRegionFactoryBean<String, Employee> getEmployee(final GemFireCache cache) {
LocalRegionFactoryBean<String, Employee> employeeRegion = new LocalRegionFactoryBean<String, Employee>();
employeeRegion.setCache(cache);
employeeRegion.setClose(false);
employeeRegion.setName("employee");
employeeRegion.setPersistent(false);
employeeRegion.setDataPolicy(DataPolicy.PRELOADED);
return employeeRegion;
}
}
@@ -0,0 +1,41 @@
package com.baeldung.spring.data.gemfire.model;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.gemfire.mapping.Region;
@Region("employee")
public class Employee {
@Id
public String name;
public double salary;
@PersistenceConstructor
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
@Override
public String toString() {
return name + " is " + salary + " years old.";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
@@ -0,0 +1,17 @@
package com.baeldung.spring.data.gemfire.repository;
import com.baeldung.spring.data.gemfire.model.Employee;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface EmployeeRepository extends CrudRepository<Employee, String> {
Employee findByName(String name);
Iterable<Employee> findBySalaryGreaterThan(double salary);
Iterable<Employee> findBySalaryLessThan(double salary);
Iterable<Employee> findBySalaryGreaterThanAndSalaryLessThan(double salary1, double salary2);
}
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:gfe-data="http://www.springframework.org/schema/data/gemfire"
xmlns:gfe="http://www.springframework.org/schema/gemfire"
xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/data/gemfire http://www.springframework.org/schema/data/gemfire/spring-data-gemfire.xsd http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd">
<context:component-scan base-package="com.baeldung.spring.data.gemfire"></context:component-scan>
<gfe:annotation-driven/>
<gfe-data:function-executions base-package="com.baeldung.spring.data.gemfire.function"/>
<!-- Declare GemFire Cache -->
<gfe:cache/>
<!-- Local region for being used by the Message -->
<gfe:local-region id="employee" value-constraint="com.baeldung.spring.data.gemfire.model.Employee" data-policy="PRELOADED"/>
<!-- Search for GemFire repositories -->
<gfe-data:repositories base-package="com.baeldung.spring.data.gemfire.repository"/>
</beans>
@@ -0,0 +1,98 @@
package com.baeldung.spring.data.gemfire.repository;
import com.baeldung.spring.data.gemfire.function.FunctionExecution;
import com.baeldung.spring.data.gemfire.function.GemfireConfiguration;
import com.baeldung.spring.data.gemfire.model.Employee;
import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import java.util.List;
import static junit.framework.Assert.assertEquals;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=GemfireConfiguration.class, loader=AnnotationConfigContextLoader.class)
public class EmployeeRepositoryIntegrationTest {
@Autowired private
EmployeeRepository employeeRepository;
@Autowired
private FunctionExecution execution;
@Test
public void whenEmployeeIsSaved_ThenAbleToRead(){
Employee employee=new Employee("John Davidson",4550.00);
employeeRepository.save(employee);
List<Employee> employees= Lists.newArrayList(employeeRepository.findAll());
assertEquals(1, employees.size());
}
@Test
public void whenSalaryGreaterThan_ThenEmployeeFound(){
Employee employee=new Employee("John Davidson",4550.00);
Employee employee1=new Employee("Adam Davidson",3500.00);
Employee employee2=new Employee("Chris Davidson",5600.00);
employeeRepository.save(employee);
employeeRepository.save(employee1);
employeeRepository.save(employee2);
List<Employee> employees= Lists.newArrayList(employeeRepository.findBySalaryGreaterThan(4000.00));
assertEquals(2,employees.size());
}
@Test
public void whenSalaryLessThan_ThenEmployeeFound(){
Employee employee=new Employee("John Davidson",4550.00);
Employee employee1=new Employee("Adam Davidson",3500.00);
Employee employee2=new Employee("Chris Davidson",5600.00);
employeeRepository.save(employee);
employeeRepository.save(employee1);
employeeRepository.save(employee2);
List<Employee> employees= Lists.newArrayList(employeeRepository.findBySalaryLessThan(4000));
assertEquals(1,employees.size());
}
@Test
public void whenSalaryBetween_ThenEmployeeFound(){
Employee employee=new Employee("John Davidson",4550.00);
Employee employee1=new Employee("Adam Davidson",3500.00);
Employee employee2=new Employee("Chris Davidson",5600.00);
employeeRepository.save(employee);
employeeRepository.save(employee1);
employeeRepository.save(employee2);
List<Employee> employees= Lists.newArrayList(employeeRepository.findBySalaryGreaterThanAndSalaryLessThan(3500,5000));
assertEquals(1,employees.size());
}
@Test
public void whenFunctionExecutedFromClient_ThenFunctionExecutedOnServer(){
execution.execute("Hello World");
}
@After
public void cleanup(){
employeeRepository.deleteAll();
}
}
@@ -0,0 +1,16 @@
## Spring Data Neo4j
### Relevant Articles:
- [Introduction to Spring Data Neo4j](http://www.baeldung.com/spring-data-neo4j-intro)
- [A Guide to Neo4J with Java](http://www.baeldung.com/java-neo4j)
### Build the Project with Tests Running
```
mvn clean install
```
### Run Tests Directly
```
mvn test
```
@@ -0,0 +1,171 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>1.0</version>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>${neo4j.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-core</artifactId>
<version>${neo4j-ogm.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-embedded-driver</artifactId>
<version>${neo4j-ogm.version}</version>
</dependency>
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>${neo4j-java-driver.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>${spring-data-neo4j.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>${spring-data-neo4j.version}</version>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>com.voodoodyne.jackson.jsog</groupId>
<artifactId>jackson-jsog</artifactId>
<version>${jackson-jsog.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-kernel</artifactId>
<version>${neo4j.version}</version>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>org.neo4j.app</groupId>
<artifactId>neo4j-server</artifactId>
<version>${neo4j.version}</version>
<type>test-jar</type>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-test</artifactId>
<version>${neo4j-ogm.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.neo4j.test</groupId>
<artifactId>neo4j-harness</artifactId>
<version>${neo4j.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-test.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*LiveTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<neo4j-java-driver.version>1.1.1</neo4j-java-driver.version>
<neo4j.version>3.1.0</neo4j.version>
<spring-data-neo4j.version>4.1.6.RELEASE</spring-data-neo4j.version>
<jackson-jsog.version>1.1</jackson-jsog.version>
<spring-boot.version>1.4.3.RELEASE</spring-boot.version>
<spring-test.version>4.3.5.RELEASE</spring-test.version>
<neo4j-ogm.version>2.1.1</neo4j-ogm.version>
</properties>
</project>
@@ -0,0 +1,27 @@
package com.baeldung.spring.data.neo4j.config;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
@ComponentScan(basePackages = { "com.baeldung.spring.data.neo4j.services" })
@Configuration
@EnableNeo4jRepositories(basePackages = "com.baeldung.spring.data.neo4j.repostory")
public class MovieDatabaseNeo4jConfiguration {
public static final String URL = System.getenv("NEO4J_URL") != null ? System.getenv("NEO4J_URL") : "http://neo4j:movies@localhost:7474";
@Bean
public org.neo4j.ogm.config.Configuration getConfiguration() {
org.neo4j.ogm.config.Configuration config = new org.neo4j.ogm.config.Configuration();
config.driverConfiguration().setDriverClassName("org.neo4j.ogm.drivers.http.driver.HttpDriver").setURI(URL);
return config;
}
@Bean
public SessionFactory getSessionFactory() {
return new SessionFactory(getConfiguration(), "com.baeldung.spring.data.neo4j.domain");
}
}
@@ -0,0 +1,32 @@
package com.baeldung.spring.data.neo4j.config;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = { "com.baeldung.spring.data.neo4j.services" })
@EnableNeo4jRepositories(basePackages = "com.baeldung.spring.data.neo4j.repostory")
@Profile({ "embedded", "test" })
public class MovieDatabaseNeo4jTestConfiguration extends Neo4jConfiguration {
@Bean
public org.neo4j.ogm.config.Configuration getConfiguration() {
final org.neo4j.ogm.config.Configuration config = new org.neo4j.ogm.config.Configuration();
config.driverConfiguration()
.setDriverClassName("org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver");
return config;
}
@Bean
public SessionFactory getSessionFactory() {
return new SessionFactory(getConfiguration(), "com.baeldung.spring.data.neo4j.domain");
}
}
@@ -0,0 +1,47 @@
package com.baeldung.spring.data.neo4j.domain;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
@NodeEntity
public class Car {
@GraphId
private Long id;
private String make;
@Relationship(direction = "INCOMING")
private Company company;
public Car(String make, String model) {
this.make = make;
this.model = model;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
private String model;
}
@@ -0,0 +1,42 @@
package com.baeldung.spring.data.neo4j.domain;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
@NodeEntity
public class Company {
private Long id;
private String name;
@Relationship(type="owns")
private Car car;
public Company(String name) {
this.name = 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;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
}
@@ -0,0 +1,62 @@
package com.baeldung.spring.data.neo4j.domain;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.voodoodyne.jackson.jsog.JSOGGenerator;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
import java.util.Collection;
import java.util.List;
@JsonIdentityInfo(generator = JSOGGenerator.class)
@NodeEntity
public class Movie {
@GraphId
Long id;
private String title;
private int released;
private String tagline;
@Relationship(type = "ACTED_IN", direction = Relationship.INCOMING)
private List<Role> roles;
public Movie() {
}
public String getTitle() {
return title;
}
public int getReleased() {
return released;
}
public String getTagline() {
return tagline;
}
public Collection<Role> getRoles() {
return roles;
}
public void setTitle(String title) {
this.title = title;
}
public void setReleased(int released) {
this.released = released;
}
public void setTagline(String tagline) {
this.tagline = tagline;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
}
@@ -0,0 +1,50 @@
package com.baeldung.spring.data.neo4j.domain;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.voodoodyne.jackson.jsog.JSOGGenerator;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
import java.util.List;
@JsonIdentityInfo(generator = JSOGGenerator.class)
@NodeEntity
public class Person {
@GraphId
Long id;
private String name;
private int born;
@Relationship(type = "ACTED_IN")
private List<Movie> movies;
public Person() {
}
public String getName() {
return name;
}
public int getBorn() {
return born;
}
public List<Movie> getMovies() {
return movies;
}
public void setName(String name) {
this.name = name;
}
public void setBorn(int born) {
this.born = born;
}
public void setMovies(List<Movie> movies) {
this.movies = movies;
}
}
@@ -0,0 +1,49 @@
package com.baeldung.spring.data.neo4j.domain;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.voodoodyne.jackson.jsog.JSOGGenerator;
import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;
import java.util.Collection;
@JsonIdentityInfo(generator = JSOGGenerator.class)
@RelationshipEntity(type = "ACTED_IN")
public class Role {
@GraphId
Long id;
private Collection<String> roles;
@StartNode
private Person person;
@EndNode
private Movie movie;
public Role() {
}
public Collection<String> getRoles() {
return roles;
}
public Person getPerson() {
return person;
}
public Movie getMovie() {
return movie;
}
public void setRoles(Collection<String> roles) {
this.roles = roles;
}
public void setPerson(Person person) {
this.person = person;
}
public void setMovie(Movie movie) {
this.movie = movie;
}
}
@@ -0,0 +1,23 @@
package com.baeldung.spring.data.neo4j.repostory;
import com.baeldung.spring.data.neo4j.domain.Movie;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@Repository
public interface MovieRepository extends GraphRepository<Movie> {
Movie findByTitle(@Param("title") String title);
@Query("MATCH (m:Movie) WHERE m.title =~ ('(?i).*'+{title}+'.*') RETURN m")
Collection<Movie> findByTitleContaining(@Param("title") String title);
@Query("MATCH (m:Movie)<-[:ACTED_IN]-(a:Person) RETURN m.title as movie, collect(a.name) as cast LIMIT {limit}")
List<Map<String, Object>> graph(@Param("limit") int limit);
}
@@ -0,0 +1,9 @@
package com.baeldung.spring.data.neo4j.repostory;
import com.baeldung.spring.data.neo4j.domain.Person;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface PersonRepository extends GraphRepository<Person> {
}
@@ -0,0 +1,50 @@
package com.baeldung.spring.data.neo4j.services;
import com.baeldung.spring.data.neo4j.repostory.MovieRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@Service
@Transactional
public class MovieService {
@Autowired
private MovieRepository movieRepository;
private Map<String, Object> toD3Format(Iterator<Map<String, Object>> result) {
List<Map<String, Object>> nodes = new ArrayList<>();
List<Map<String, Object>> rels = new ArrayList<>();
int i = 0;
while (result.hasNext()) {
Map<String, Object> row = result.next();
nodes.add(map("title", row.get("movie"), "label", "movie"));
int target = i;
i++;
for (Object name : (Collection) row.get("cast")) {
Map<String, Object> actor = map("title", name, "label", "actor");
int source = nodes.indexOf(actor);
if (source == -1) {
nodes.add(actor);
source = i++;
}
rels.add(map("source", source, "target", target));
}
}
return map("nodes", nodes, "links", rels);
}
private Map<String, Object> map(String key1, Object value1, String key2, Object value2) {
Map<String, Object> result = new HashMap<>(2);
result.put(key1, value1);
result.put(key2, value2);
return result;
}
public Map<String, Object> graph(int limit) {
Iterator<Map<String, Object>> result = movieRepository.graph(limit).iterator();
return toD3Format(result);
}
}
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>web - %date [%thread] %-5level %logger{36} - %message%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

@@ -0,0 +1,60 @@
package com.baeldung.neo4j;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.neo4j.driver.v1.AuthTokens;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.GraphDatabase;
import org.neo4j.driver.v1.Session;
import org.neo4j.driver.v1.StatementResult;
@Ignore
public class Neo4JServerLiveTest {
@Test
public void standAloneDriver() {
Driver driver = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("neo4j", "12345"));
Session session = driver.session();
session.run("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
"-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" +
"RETURN baeldung, tesla");
StatementResult result = session.run("MATCH (company:Company)-[:owns]-> (car:Car)" +
"WHERE car.make='tesla' and car.model='modelX'" +
"RETURN company.name");
Assert.assertTrue(result.hasNext());
Assert.assertEquals(result.next().get("company.name").asString(), "Baeldung");
session.close();
driver.close();
}
@Test
public void standAloneJdbc() throws Exception {
Connection con = DriverManager.getConnection("jdbc:neo4j:bolt://localhost/?user=neo4j,password=12345,scheme=basic");
// Querying
try (Statement stmt = con.createStatement()) {
stmt.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " +
"-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" +
"RETURN baeldung, tesla");
ResultSet rs = stmt.executeQuery("MATCH (company:Company)-[:owns]-> (car:Car)" +
"WHERE car.make='tesla' and car.model='modelX'" +
"RETURN company.name");
while (rs.next()) {
Assert.assertEquals(rs.getString("company.name"), "Baeldung");
}
}
con.close();
}
}

Some files were not shown because too many files have changed in this diff Show More