diff --git a/core-java/src/test/java/org/baeldung/java/collections/ArrayListTest.java b/core-java/src/test/java/org/baeldung/java/collections/ArrayListTest.java index d7a69c42c7..7a80d802e9 100644 --- a/core-java/src/test/java/org/baeldung/java/collections/ArrayListTest.java +++ b/core-java/src/test/java/org/baeldung/java/collections/ArrayListTest.java @@ -7,8 +7,7 @@ import org.junit.Test; import java.util.*; import java.util.stream.*; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toSet; +import static java.util.stream.Collectors.*; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.*; @@ -22,7 +21,7 @@ public class ArrayListTest { List xs = LongStream.range(0, 16) .boxed() .map(Long::toHexString) - .collect(toList()); + .collect(toCollection(ArrayList::new)); stringsToSearch = new ArrayList<>(xs); stringsToSearch.addAll(xs); } @@ -57,8 +56,8 @@ public class ArrayListTest { @Test public void givenCollection_whenAddToArrayList_thenIsAdded() { List xs = new ArrayList<>(Arrays.asList(1L, 2L, 3L)); - Collection ys = LongStream.range(4, 10).boxed().collect(toList()); - xs.addAll(0, ys); + LongStream.range(4, 10).boxed() + .collect(collectingAndThen(toList(), ys -> xs.addAll(0, ys))); assertThat(Arrays.asList(4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L), equalTo(xs)); } @@ -92,7 +91,7 @@ public class ArrayListTest { List result = stringsToSearch .stream() .filter(matchingStrings::contains) - .collect(toList()); + .collect(toCollection(ArrayList::new)); assertEquals(6, result.size()); } @@ -107,7 +106,7 @@ public class ArrayListTest { @Test public void givenIndex_whenRemove_thenCorrectElementRemoved() { - List xs = IntStream.range(0, 10).boxed().collect(toList()); + List xs = IntStream.range(0, 10).boxed().collect(toCollection(ArrayList::new)); Collections.reverse(xs); xs.remove(0); @@ -119,7 +118,7 @@ public class ArrayListTest { @Test public void givenListIterator_whenReverseTraversal_thenRetrieveElementsInOppositeOrder() { - List xs = IntStream.range(0, 10).boxed().collect(toList()); + List xs = IntStream.range(0, 10).boxed().collect(toCollection(ArrayList::new)); ListIterator it = xs.listIterator(xs.size()); List result = new ArrayList<>(xs.size()); while (it.hasPrevious()) { diff --git a/eclipse/src/main/java/org/baeldung/equalshashcode/entities/ComplexClass.java b/eclipse/src/main/java/org/baeldung/equalshashcode/entities/ComplexClass.java index f8c85ab8b5..3f7723facd 100644 --- a/eclipse/src/main/java/org/baeldung/equalshashcode/entities/ComplexClass.java +++ b/eclipse/src/main/java/org/baeldung/equalshashcode/entities/ComplexClass.java @@ -5,63 +5,59 @@ import java.util.HashSet; public class ComplexClass { - private ArrayList genericArrayList; - private HashSet integerHashSet; + private ArrayList genericArrayList; + private HashSet integerHashSet; - public ComplexClass(ArrayList genericArrayList, - HashSet integerHashSet) { - super(); - this.genericArrayList = genericArrayList; - this.integerHashSet = integerHashSet; - } + public ComplexClass(ArrayList genericArrayList, HashSet integerHashSet) { + super(); + this.genericArrayList = genericArrayList; + this.integerHashSet = integerHashSet; + } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime - * result - + ((genericArrayList == null) ? 0 : genericArrayList.hashCode()); - result = prime * result - + ((integerHashSet == null) ? 0 : integerHashSet.hashCode()); - return result; - } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((genericArrayList == null) ? 0 : genericArrayList.hashCode()); + result = prime * result + ((integerHashSet == null) ? 0 : integerHashSet.hashCode()); + return result; + } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof ComplexClass)) - return false; - ComplexClass other = (ComplexClass) obj; - if (genericArrayList == null) { - if (other.genericArrayList != null) - return false; - } else if (!genericArrayList.equals(other.genericArrayList)) - return false; - if (integerHashSet == null) { - if (other.integerHashSet != null) - return false; - } else if (!integerHashSet.equals(other.integerHashSet)) - return false; - return true; - } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof ComplexClass)) + return false; + ComplexClass other = (ComplexClass) obj; + if (genericArrayList == null) { + if (other.genericArrayList != null) + return false; + } else if (!genericArrayList.equals(other.genericArrayList)) + return false; + if (integerHashSet == null) { + if (other.integerHashSet != null) + return false; + } else if (!integerHashSet.equals(other.integerHashSet)) + return false; + return true; + } - protected ArrayList getGenericArrayList() { - return genericArrayList; - } + protected ArrayList getGenericArrayList() { + return genericArrayList; + } - protected void setGenericArrayList(ArrayList genericArrayList) { - this.genericArrayList = genericArrayList; - } + protected void setGenericArrayList(ArrayList genericArrayList) { + this.genericArrayList = genericArrayList; + } - protected HashSet getIntegerHashSet() { - return integerHashSet; - } + protected HashSet getIntegerHashSet() { + return integerHashSet; + } - protected void setIntegerHashSet(HashSet integerHashSet) { - this.integerHashSet = integerHashSet; - } + protected void setIntegerHashSet(HashSet integerHashSet) { + this.integerHashSet = integerHashSet; + } } diff --git a/eclipse/src/main/java/org/baeldung/equalshashcode/entities/PrimitiveClass.java b/eclipse/src/main/java/org/baeldung/equalshashcode/entities/PrimitiveClass.java index 6cd4af5fdb..ebe005688c 100644 --- a/eclipse/src/main/java/org/baeldung/equalshashcode/entities/PrimitiveClass.java +++ b/eclipse/src/main/java/org/baeldung/equalshashcode/entities/PrimitiveClass.java @@ -2,53 +2,53 @@ package org.baeldung.equalshashcode.entities; public class PrimitiveClass { - private boolean primitiveBoolean; - private int primitiveInt; + private boolean primitiveBoolean; + private int primitiveInt; - public PrimitiveClass(boolean primitiveBoolean, int primitiveInt) { - super(); - this.primitiveBoolean = primitiveBoolean; - this.primitiveInt = primitiveInt; - } + public PrimitiveClass(boolean primitiveBoolean, int primitiveInt) { + super(); + this.primitiveBoolean = primitiveBoolean; + this.primitiveInt = primitiveInt; + } - protected boolean isPrimitiveBoolean() { - return primitiveBoolean; - } + protected boolean isPrimitiveBoolean() { + return primitiveBoolean; + } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (primitiveBoolean ? 1231 : 1237); - result = prime * result + primitiveInt; - return result; - } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (primitiveBoolean ? 1231 : 1237); + result = prime * result + primitiveInt; + return result; + } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - PrimitiveClass other = (PrimitiveClass) obj; - if (primitiveBoolean != other.primitiveBoolean) - return false; - if (primitiveInt != other.primitiveInt) - return false; - return true; - } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PrimitiveClass other = (PrimitiveClass) obj; + if (primitiveBoolean != other.primitiveBoolean) + return false; + if (primitiveInt != other.primitiveInt) + return false; + return true; + } - protected void setPrimitiveBoolean(boolean primitiveBoolean) { - this.primitiveBoolean = primitiveBoolean; - } + protected void setPrimitiveBoolean(boolean primitiveBoolean) { + this.primitiveBoolean = primitiveBoolean; + } - protected int getPrimitiveInt() { - return primitiveInt; - } + protected int getPrimitiveInt() { + return primitiveInt; + } - protected void setPrimitiveInt(int primitiveInt) { - this.primitiveInt = primitiveInt; - } + protected void setPrimitiveInt(int primitiveInt) { + this.primitiveInt = primitiveInt; + } } diff --git a/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Rectangle.java b/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Rectangle.java index 61d20cbb05..315ef41a12 100644 --- a/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Rectangle.java +++ b/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Rectangle.java @@ -1,62 +1,60 @@ package org.baeldung.equalshashcode.entities; public class Rectangle extends Shape { - private double width; - private double length; + private double width; + private double length; - public Rectangle(double width, double length) { - this.width = width; - this.length = length; - } + public Rectangle(double width, double length) { + this.width = width; + this.length = length; + } - @Override - public double area() { - // A = w * l - return width * length; - } + @Override + public double area() { + // A = w * l + return width * length; + } - @Override - public double perimeter() { - // P = 2(w + l) - return 2 * (width + length); - } + @Override + public double perimeter() { + // P = 2(w + l) + return 2 * (width + length); + } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(length); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(width); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(length); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(width); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Rectangle other = (Rectangle) obj; - if (Double.doubleToLongBits(length) != Double - .doubleToLongBits(other.length)) - return false; - if (Double.doubleToLongBits(width) != Double - .doubleToLongBits(other.width)) - return false; - return true; - } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Rectangle other = (Rectangle) obj; + if (Double.doubleToLongBits(length) != Double.doubleToLongBits(other.length)) + return false; + if (Double.doubleToLongBits(width) != Double.doubleToLongBits(other.width)) + return false; + return true; + } - protected double getWidth() { - return width; - } + protected double getWidth() { + return width; + } - protected double getLength() { - return length; - } + protected double getLength() { + return length; + } } \ No newline at end of file diff --git a/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Shape.java b/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Shape.java index 7f779e6ef2..3bfc81da8f 100644 --- a/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Shape.java +++ b/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Shape.java @@ -1,7 +1,7 @@ package org.baeldung.equalshashcode.entities; public abstract class Shape { - public abstract double area(); + public abstract double area(); - public abstract double perimeter(); + public abstract double perimeter(); } diff --git a/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Square.java b/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Square.java index 0bebc1e380..f11e34f0ba 100644 --- a/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Square.java +++ b/eclipse/src/main/java/org/baeldung/equalshashcode/entities/Square.java @@ -4,44 +4,55 @@ import java.awt.Color; public class Square extends Rectangle { - Color color; + Color color; - public Square(double width, Color color) { - super(width, width); - this.color = color; - } + public Square(double width, Color color) { + super(width, width); + this.color = color; + } - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((color == null) ? 0 : color.hashCode()); - return result; - } + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((color == null) ? 0 : color.hashCode()); + return result; + } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - Square other = (Square) obj; - if (color == null) { - if (other.color != null) - return false; - } else if (!color.equals(other.color)) - return false; - return true; - } + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (!(obj instanceof Square)) { + return false; + } + Square other = (Square) obj; + if (color == null) { + if (other.color != null) { + return false; + } + } else if (!color.equals(other.color)) { + return false; + } + return true; + } - protected Color getColor() { - return color; - } + protected Color getColor() { + return color; + } - protected void setColor(Color color) { - this.color = color; - } + protected void setColor(Color color) { + this.color = color; + } } diff --git a/eclipse/src/test/java/org/baeldung/equalshashcode/entities/ComplexClassTest.java b/eclipse/src/test/java/org/baeldung/equalshashcode/entities/ComplexClassTest.java index 2cca44bb9e..09123e988b 100644 --- a/eclipse/src/test/java/org/baeldung/equalshashcode/entities/ComplexClassTest.java +++ b/eclipse/src/test/java/org/baeldung/equalshashcode/entities/ComplexClassTest.java @@ -8,32 +8,27 @@ import org.junit.Test; public class ComplexClassTest { - @Test - public void testEqualsAndHashcodes() { - - ArrayList strArrayList = new ArrayList(); - strArrayList.add("abc"); - strArrayList.add("def"); - ComplexClass aObject = new ComplexClass(strArrayList, new HashSet(45,67)); - ComplexClass bObject = new ComplexClass(strArrayList, new HashSet(45,67)); - ComplexClass cObject = new ComplexClass(strArrayList, new HashSet(45,67)); - - ArrayList strArrayListD = new ArrayList(); - strArrayListD.add("lmn"); - strArrayListD.add("pqr"); - ComplexClass dObject = new ComplexClass(strArrayListD, new HashSet(45,67)); - - // equals() - Assert.assertTrue(aObject.equals(aObject)); - Assert.assertTrue(aObject.equals(bObject) && bObject.equals(aObject)); - Assert.assertTrue(aObject.equals(bObject)); - Assert.assertTrue(bObject.equals(cObject)); - Assert.assertTrue(aObject.equals(cObject)); - // hashCode() - Assert.assertTrue(aObject.hashCode() == bObject.hashCode()); - // non-equal objects are not equals() and have different hashCode() - Assert.assertFalse(aObject.equals(dObject)); - Assert.assertFalse(aObject.hashCode() == dObject.hashCode()); - } + @Test + public void testEqualsAndHashcodes() { + + ArrayList strArrayList = new ArrayList(); + strArrayList.add("abc"); + strArrayList.add("def"); + ComplexClass aObject = new ComplexClass(strArrayList, new HashSet(45, 67)); + ComplexClass bObject = new ComplexClass(strArrayList, new HashSet(45, 67)); + + ArrayList strArrayListD = new ArrayList(); + strArrayListD.add("lmn"); + strArrayListD.add("pqr"); + ComplexClass dObject = new ComplexClass(strArrayListD, new HashSet(45, 67)); + + // equals() + Assert.assertTrue(aObject.equals(bObject) && bObject.equals(aObject)); + // hashCode() + Assert.assertTrue(aObject.hashCode() == bObject.hashCode()); + // non-equal objects are not equals() and have different hashCode() + Assert.assertFalse(aObject.equals(dObject)); + Assert.assertFalse(aObject.hashCode() == dObject.hashCode()); + } } diff --git a/eclipse/src/test/java/org/baeldung/equalshashcode/entities/PrimitiveClassTest.java b/eclipse/src/test/java/org/baeldung/equalshashcode/entities/PrimitiveClassTest.java index 009753d1ae..feb04d65ff 100644 --- a/eclipse/src/test/java/org/baeldung/equalshashcode/entities/PrimitiveClassTest.java +++ b/eclipse/src/test/java/org/baeldung/equalshashcode/entities/PrimitiveClassTest.java @@ -5,25 +5,20 @@ import org.junit.Test; public class PrimitiveClassTest { - @Test - public void testTwoEqualsObjects() { + @Test + public void testTwoEqualsObjects() { - PrimitiveClass aObject = new PrimitiveClass(false, 2); - PrimitiveClass bObject = new PrimitiveClass(false, 2); - PrimitiveClass cObject = new PrimitiveClass(false, 2); - PrimitiveClass dObject = new PrimitiveClass(true, 2); + PrimitiveClass aObject = new PrimitiveClass(false, 2); + PrimitiveClass bObject = new PrimitiveClass(false, 2); + PrimitiveClass dObject = new PrimitiveClass(true, 2); - // equals() - Assert.assertTrue(aObject.equals(aObject)); - Assert.assertTrue(aObject.equals(bObject) && bObject.equals(aObject)); - Assert.assertTrue(aObject.equals(bObject)); - Assert.assertTrue(bObject.equals(cObject)); - Assert.assertTrue(aObject.equals(cObject)); - // hashCode() - Assert.assertTrue(aObject.hashCode() == bObject.hashCode()); - // non-equal objects are not equals() and have different hashCode() - Assert.assertFalse(aObject.equals(dObject)); - Assert.assertFalse(aObject.hashCode() == dObject.hashCode()); - } + // equals() + Assert.assertTrue(aObject.equals(bObject) && bObject.equals(aObject)); + // hashCode() + Assert.assertTrue(aObject.hashCode() == bObject.hashCode()); + // non-equal objects are not equals() and have different hashCode() + Assert.assertFalse(aObject.equals(dObject)); + Assert.assertFalse(aObject.hashCode() == dObject.hashCode()); + } } diff --git a/eclipse/src/test/java/org/baeldung/equalshashcode/entities/SquareClassTest.java b/eclipse/src/test/java/org/baeldung/equalshashcode/entities/SquareClassTest.java index 1290f57c6d..53ca199405 100644 --- a/eclipse/src/test/java/org/baeldung/equalshashcode/entities/SquareClassTest.java +++ b/eclipse/src/test/java/org/baeldung/equalshashcode/entities/SquareClassTest.java @@ -7,26 +7,21 @@ import org.junit.Test; public class SquareClassTest { - @Test - public void testEqualsAndHashcodes() { - - Square aObject = new Square(10, Color.BLUE); - Square bObject = new Square(10, Color.BLUE); - Square cObject = new Square(10, Color.BLUE); - - Square dObject = new Square(20, Color.BLUE); - - // equals() - Assert.assertTrue(aObject.equals(aObject)); - Assert.assertTrue(aObject.equals(bObject) && bObject.equals(aObject)); - Assert.assertTrue(aObject.equals(bObject)); - Assert.assertTrue(bObject.equals(cObject)); - Assert.assertTrue(aObject.equals(cObject)); - // hashCode() - Assert.assertTrue(aObject.hashCode() == bObject.hashCode()); - // non-equal objects are not equals() and have different hashCode() - Assert.assertFalse(aObject.equals(dObject)); - Assert.assertFalse(aObject.hashCode() == dObject.hashCode()); - } + @Test + public void testEqualsAndHashcodes() { + + Square aObject = new Square(10, Color.BLUE); + Square bObject = new Square(10, Color.BLUE); + + Square dObject = new Square(20, Color.BLUE); + + // equals() + Assert.assertTrue(aObject.equals(bObject) && bObject.equals(aObject)); + // hashCode() + Assert.assertTrue(aObject.hashCode() == bObject.hashCode()); + // non-equal objects are not equals() and have different hashCode() + Assert.assertFalse(aObject.equals(dObject)); + Assert.assertFalse(aObject.hashCode() == dObject.hashCode()); + } } diff --git a/flyway-migration/db/migration/V2_0__create_department_schema.sql b/flyway-migration/db/migration/V2_0__create_department_schema.sql new file mode 100644 index 0000000000..2b9d3364a5 --- /dev/null +++ b/flyway-migration/db/migration/V2_0__create_department_schema.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS `department` ( + +`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY, +`name` varchar(20) + +)ENGINE=InnoDB DEFAULT CHARSET=UTF8; + +ALTER TABLE `employee` ADD `dept_id` int AFTER `email`; \ No newline at end of file diff --git a/flyway-migration/pom.xml b/flyway-migration/pom.xml index e3e29cd43f..6e9d683a0e 100644 --- a/flyway-migration/pom.xml +++ b/flyway-migration/pom.xml @@ -23,6 +23,7 @@ org.apache.maven.plugins maven-compiler-plugin + 3.5.1 1.8 1.8 diff --git a/java-cassandra/pom.xml b/java-cassandra/pom.xml new file mode 100644 index 0000000000..265a230eb4 --- /dev/null +++ b/java-cassandra/pom.xml @@ -0,0 +1,102 @@ + + 4.0.0 + com.baeldung + cassandra-java-client + 1.0.0-SNAPSHOT + + cassandra-java-client + + + UTF-8 + + + 1.7.21 + 1.1.7 + + + 1.3 + 4.12 + 1.10.19 + 6.8 + 3.5.1 + + + 3.5.1 + + + 3.1.0 + + + + + + com.datastax.cassandra + cassandra-driver-core + ${cassandra-driver-core.version} + true + + + + + org.cassandraunit + cassandra-unit + 3.0.0.1 + + + + + com.google.guava + guava + 19.0 + + + + + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + + junit + junit + ${junit.version} + test + + + + + java-cassandra + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + + diff --git a/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraClient.java b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraClient.java new file mode 100644 index 0000000000..c67a2c2ddb --- /dev/null +++ b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraClient.java @@ -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(); + } +} diff --git a/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraConnector.java b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraConnector.java new file mode 100644 index 0000000000..e035335ca0 --- /dev/null +++ b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/CassandraConnector.java @@ -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(); + } +} diff --git a/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/domain/Book.java b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/domain/Book.java new file mode 100644 index 0000000000..e6c7753eb3 --- /dev/null +++ b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/domain/Book.java @@ -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; + } +} diff --git a/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/BookRepository.java b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/BookRepository.java new file mode 100644 index 0000000000..31e2969e01 --- /dev/null +++ b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/BookRepository.java @@ -0,0 +1,177 @@ +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 books = new ArrayList(); + + 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 selectAll() { + StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME); + + final String query = sb.toString(); + ResultSet rs = session.execute(query); + + List books = new ArrayList(); + + 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 selectAllBookByTitle() { + StringBuilder sb = new StringBuilder("SELECT * FROM ").append(TABLE_NAME_BY_TITLE); + + final String query = sb.toString(); + ResultSet rs = session.execute(query); + + List books = new ArrayList(); + + 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); + } +} diff --git a/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepository.java b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepository.java new file mode 100644 index 0000000000..f15558f040 --- /dev/null +++ b/java-cassandra/src/main/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepository.java @@ -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); + } +} diff --git a/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/BookRepositoryIntegrationTest.java b/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/BookRepositoryIntegrationTest.java new file mode 100644 index 0000000000..62eae94c7c --- /dev/null +++ b/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/BookRepositoryIntegrationTest.java @@ -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 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 books = bookRepository.selectAll(); + + assertEquals(1, books.size()); + assertTrue(books.stream().anyMatch(b -> b.getTitle().equals("Effective Java"))); + + List 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 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 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(); + } +} diff --git a/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepositoryIntegrationTest.java b/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepositoryIntegrationTest.java new file mode 100644 index 0000000000..9df46b3176 --- /dev/null +++ b/java-cassandra/src/test/java/com/baeldung/cassandra/java/client/repository/KeyspaceRepositoryIntegrationTest.java @@ -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 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(); + } +} diff --git a/pom.xml b/pom.xml index db3fa8a21c..2f588c032c 100644 --- a/pom.xml +++ b/pom.xml @@ -129,7 +129,7 @@ redis xstream - + java-cassandra diff --git a/spring-jpa/src/main/java/org/baeldung/persistence/multiple/dao/user/PossessionRepository.java b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/dao/user/PossessionRepository.java new file mode 100644 index 0000000000..34913632d8 --- /dev/null +++ b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/dao/user/PossessionRepository.java @@ -0,0 +1,8 @@ +package org.baeldung.persistence.multiple.dao.user; + +import org.baeldung.persistence.multiple.model.user.Possession; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PossessionRepository extends JpaRepository { + +} diff --git a/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/Possession.java b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/Possession.java new file mode 100644 index 0000000000..97b5803d73 --- /dev/null +++ b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/Possession.java @@ -0,0 +1,86 @@ +package org.baeldung.persistence.multiple.model.user; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(schema = "spring_jpa_user") +public class Possession { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String name; + + public Possession() { + super(); + } + + public Possession(final String name) { + super(); + + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + (int) (id ^ (id >>> 32)); + result = (prime * result) + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Possession other = (Possession) obj; + if (id != other.id) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Possesion [id=").append(id).append(", name=").append(name).append("]"); + return builder.toString(); + } + +} diff --git a/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/User.java b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/User.java index 305568bad8..1c6399dc44 100644 --- a/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/User.java +++ b/spring-jpa/src/main/java/org/baeldung/persistence/multiple/model/user/User.java @@ -1,10 +1,13 @@ package org.baeldung.persistence.multiple.model.user; +import java.util.List; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @@ -22,6 +25,9 @@ public class User { private int age; + @OneToMany + List possessionList; + public User() { super(); } @@ -58,6 +64,14 @@ public class User { this.age = age; } + public List getPossessionList() { + return possessionList; + } + + public void setPossessionList(List possessionList) { + this.possessionList = possessionList; + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBIntegrationTest.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBIntegrationTest.java index 7e6b2722fa..f20af34057 100644 --- a/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBIntegrationTest.java +++ b/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBIntegrationTest.java @@ -1,14 +1,18 @@ package org.baeldung.persistence.service; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.util.Arrays; + import org.baeldung.config.ProductConfig; import org.baeldung.config.UserConfig; import org.baeldung.persistence.multiple.dao.product.ProductRepository; +import org.baeldung.persistence.multiple.dao.user.PossessionRepository; import org.baeldung.persistence.multiple.dao.user.UserRepository; import org.baeldung.persistence.multiple.model.product.Product; +import org.baeldung.persistence.multiple.model.user.Possession; import org.baeldung.persistence.multiple.model.user.User; import org.junit.Test; import org.junit.runner.RunWith; @@ -16,15 +20,20 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { UserConfig.class, ProductConfig.class }) +@EnableTransactionManagement public class JpaMultipleDBIntegrationTest { @Autowired private UserRepository userRepository; + @Autowired + private PossessionRepository possessionRepository; + @Autowired private ProductRepository productRepository; @@ -37,9 +46,14 @@ public class JpaMultipleDBIntegrationTest { user.setName("John"); user.setEmail("john@test.com"); user.setAge(20); + Possession p = new Possession("sample"); + p = possessionRepository.save(p); + user.setPossessionList(Arrays.asList(p)); user = userRepository.save(user); - - assertNotNull(userRepository.findOne(user.getId())); + final User result = userRepository.findOne(user.getId()); + assertNotNull(result); + System.out.println(result.getPossessionList()); + assertTrue(result.getPossessionList().size() == 1); } @Test diff --git a/spring-mvc-web-vs-initializer/.gitignore b/spring-mvc-web-vs-initializer/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-mvc-web-vs-initializer/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/pom.xml b/spring-mvc-web-vs-initializer/pom.xml new file mode 100644 index 0000000000..0d735e7188 --- /dev/null +++ b/spring-mvc-web-vs-initializer/pom.xml @@ -0,0 +1,201 @@ + + 4.0.0 + com.baeldung + spring-mvc-web-vs-initializer + 0.1-SNAPSHOT + + spring-mvc-web-vs-initializer + war + + + org.springframework.boot + spring-boot-starter-parent + 1.3.6.RELEASE + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + + org.springframework + spring-web + + + org.springframework + spring-webmvc + + + org.springframework + spring-context + + + + + + javax.servlet + javax.servlet-api + provided + + + + javax.servlet + jstl + runtime + + + + + + com.google.guava + guava + ${guava.version} + + + + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-classic + + + + org.slf4j + jcl-over-slf4j + + + + org.slf4j + log4j-over-slf4j + + + + + + org.springframework + spring-test + test + + + + junit + junit + test + + + + org.assertj + assertj-core + 3.5.1 + test + + + + org.hamcrest + hamcrest-core + test + + + org.hamcrest + hamcrest-library + test + + + + org.mockito + mockito-core + test + + + + org.easymock + easymock + 3.4 + test + + + + + + + + + + org.springframework + spring-framework-bom + ${org.springframework.version} + pom + import + + + + org.springframework + spring-core + ${org.springframework.version} + + + + + + + + spring-mvc-web-vs-initializer + + + src/main/resources + true + + + + + + + + 4.3.1.RELEASE + 4.0.4.RELEASE + 3.20.0-GA + 1.2 + + + 4.3.11.Final + 5.1.38 + + + 1.7.13 + 1.1.3 + + + 5.2.2.Final + + + 19.0 + 3.4 + + + 1.3 + 4.12 + 1.10.19 + + 4.4.1 + 4.5 + + 2.9.0 + + + 3.5.1 + 2.6 + 2.19.1 + 2.7 + 1.4.18 + + + + \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/AppInitializer.java b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/AppInitializer.java new file mode 100644 index 0000000000..21e33820ca --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/AppInitializer.java @@ -0,0 +1,26 @@ +package org.baeldung.config; + +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.ContextLoaderListener; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; + +public class AppInitializer implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext container) throws ServletException { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setConfigLocation("org.baeldung.config"); + + container.addListener(new ContextLoaderListener(context)); + + ServletRegistration.Dynamic dispatcher = container.addServlet("java-servlet", new DispatcherServlet(context)); + dispatcher.setLoadOnStartup(1); + dispatcher.addMapping("/java-servlet/*"); + } + +} diff --git a/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/MvcConfig.java b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/MvcConfig.java new file mode 100644 index 0000000000..d460113458 --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/config/MvcConfig.java @@ -0,0 +1,25 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; + +@Configuration +@EnableWebMvc +@ComponentScan(basePackages = "org.baeldung.controller.java") +public class MvcConfig extends WebMvcConfigurerAdapter { + + @Bean + public ViewResolver viewResolver() { + InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setPrefix("/WEB-INF/view/"); + viewResolver.setSuffix(".jsp"); + + return viewResolver; + } + +} diff --git a/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/java/JavaController.java b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/java/JavaController.java new file mode 100644 index 0000000000..c979c88b34 --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/java/JavaController.java @@ -0,0 +1,18 @@ +package org.baeldung.controller.java; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +@Controller +public class JavaController { + + @RequestMapping(value = "/endpoint") + public ModelAndView handleRequestFromJavaConfiguredServlet() { + ModelAndView mv = new ModelAndView(); + mv.setViewName("from-java"); + + return mv; + } + +} \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/xml/XmlController.java b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/xml/XmlController.java new file mode 100644 index 0000000000..bdefc1781c --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/java/org/baeldung/controller/xml/XmlController.java @@ -0,0 +1,18 @@ +package org.baeldung.controller.xml; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +@Controller +public class XmlController { + + @RequestMapping(value = "/endpoint") + public ModelAndView handleRequestFromXmlConfiguredServlet() { + ModelAndView mv = new ModelAndView(); + mv.setViewName("from-xml"); + + return mv; + } + +} \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/src/main/resources/mvc-configuration.xml b/spring-mvc-web-vs-initializer/src/main/resources/mvc-configuration.xml new file mode 100644 index 0000000000..7505614c99 --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/resources/mvc-configuration.xml @@ -0,0 +1,20 @@ + + + + + + + + + /WEB-INF/view/ + + + .jsp + + + + \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/view/from-java.jsp b/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/view/from-java.jsp new file mode 100644 index 0000000000..e54d7520dc --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/view/from-java.jsp @@ -0,0 +1,7 @@ + + + + +

Java

+ + \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/view/from-xml.jsp b/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/view/from-xml.jsp new file mode 100644 index 0000000000..986010c183 --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/view/from-xml.jsp @@ -0,0 +1,7 @@ + + + + +

XML

+ + \ No newline at end of file diff --git a/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/web.xml b/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..9bebc263be --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,24 @@ + + + + xml-servlet + + org.springframework.web.servlet.DispatcherServlet + + 1 + + contextConfigLocation + classpath*:mvc-configuration.xml + + + + + xml-servlet + /xml-servlet/* + + + diff --git a/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/JavaServletTest.java b/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/JavaServletTest.java new file mode 100644 index 0000000000..99b5ef8c2f --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/JavaServletTest.java @@ -0,0 +1,45 @@ +package org.baeldung.controller; + +import org.baeldung.config.MvcConfig; +import org.junit.Assert; +import org.junit.Before; +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.web.AnnotationConfigWebContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.ModelAndView; + + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(loader=AnnotationConfigWebContextLoader.class, classes = MvcConfig.class) +public class JavaServletTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + @Before + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void testJavaEndpoint() throws Exception { + ModelAndView mv = this.mockMvc.perform(MockMvcRequestBuilders.get("/endpoint")) + .andReturn() + .getModelAndView(); + + // validate view name + Assert.assertSame(mv.getViewName(), "from-java"); + } + +} diff --git a/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/XmlServletTest.java b/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/XmlServletTest.java new file mode 100644 index 0000000000..e7695e36c0 --- /dev/null +++ b/spring-mvc-web-vs-initializer/src/test/java/org/baeldung/controller/XmlServletTest.java @@ -0,0 +1,44 @@ +package org.baeldung.controller; + +import org.junit.Assert; +import org.junit.Before; +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.web.GenericXmlWebContextLoader; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.ModelAndView; + + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@ContextConfiguration(loader=GenericXmlWebContextLoader.class, locations = "classpath*:mvc-configuration.xml") +public class XmlServletTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext wac; + + @Before + public void setUp() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); + } + + @Test + public void testXmlEndpoint() throws Exception { + ModelAndView mv = this.mockMvc.perform(MockMvcRequestBuilders.get("/endpoint")) + .andReturn() + .getModelAndView(); + + // validate view name + Assert.assertSame(mv.getViewName(), "from-xml"); + } + +} diff --git a/spring-rest/pom.xml b/spring-rest/pom.xml index e28f7e7e33..0c0d6219dd 100644 --- a/spring-rest/pom.xml +++ b/spring-rest/pom.xml @@ -15,10 +15,7 @@ - - org.springframework.boot - spring-boot-starter-security - + org.springframework.boot spring-boot-starter-thymeleaf @@ -74,6 +71,11 @@ com.fasterxml.jackson.core jackson-databind + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + com.thoughtworks.xstream @@ -146,11 +148,19 @@ spring-test + + com.jayway.restassured + rest-assured + ${rest-assured.version} + + + com.google.protobuf protobuf-java 2.6.1 + com.esotericsoftware kryo @@ -231,10 +241,6 @@ 4.3.11.Final 5.1.39 - - - 2.7.2 - 5.2.2.Final diff --git a/spring-rest/src/main/java/org/baeldung/config/WebConfig.java b/spring-rest/src/main/java/org/baeldung/config/WebConfig.java index d5cd6e1eae..d116148f09 100644 --- a/spring-rest/src/main/java/org/baeldung/config/WebConfig.java +++ b/spring-rest/src/main/java/org/baeldung/config/WebConfig.java @@ -15,6 +15,11 @@ import org.springframework.oxm.xstream.XStreamMarshaller; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +/* + * Please note that main web configuration is in src/main/webapp/WEB-INF/api-servlet.xml + * + */ + @Configuration @EnableWebMvc @ComponentScan({ "org.baeldung.web" }) diff --git a/spring-rest/src/main/java/org/baeldung/web/controller/FooController.java b/spring-rest/src/main/java/org/baeldung/web/controller/FooController.java index 386c64bb09..dd1e3ca222 100644 --- a/spring-rest/src/main/java/org/baeldung/web/controller/FooController.java +++ b/spring-rest/src/main/java/org/baeldung/web/controller/FooController.java @@ -35,7 +35,6 @@ public class FooController { @ResponseStatus(HttpStatus.OK) @ResponseBody public Foo updateFoo(@PathVariable("id") final String id, @RequestBody final Foo foo) { - System.out.println(foo); return foo; } diff --git a/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml b/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml index 5afc637ece..c08faaf70d 100644 --- a/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml +++ b/spring-rest/src/main/webapp/WEB-INF/api-servlet.xml @@ -8,7 +8,12 @@ - + + + + + + diff --git a/spring-rest/src/main/webapp/WEB-INF/web.xml b/spring-rest/src/main/webapp/WEB-INF/web.xml index 01e7620c44..a439de8a05 100644 --- a/spring-rest/src/main/webapp/WEB-INF/web.xml +++ b/spring-rest/src/main/webapp/WEB-INF/web.xml @@ -8,7 +8,7 @@ Spring MVC Application - + contextClass org.springframework.web.context.support.AnnotationConfigWebApplicationContext @@ -18,7 +18,7 @@ contextConfigLocation org.baeldung.config - + org.springframework.web.context.ContextLoaderListener diff --git a/spring-rest/src/test/java/org/baeldung/web/test/RequestMappingLiveTest.java b/spring-rest/src/test/java/org/baeldung/web/test/RequestMappingLiveTest.java new file mode 100644 index 0000000000..fd349f1e44 --- /dev/null +++ b/spring-rest/src/test/java/org/baeldung/web/test/RequestMappingLiveTest.java @@ -0,0 +1,62 @@ +package org.baeldung.web.test; + +import static org.hamcrest.Matchers.equalTo; + +import org.junit.Test; + +import com.jayway.restassured.RestAssured; + +public class RequestMappingLiveTest { + private static String BASE_URI = "http://localhost:8080/spring-rest/ex/"; + + @Test + public void givenSimplePath_whenGetFoos_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "foos").then().assertThat().body(equalTo("Simple Get some Foos")); + } + + @Test + public void whenPostFoos_thenOk() { + RestAssured.given().accept("text/html").post(BASE_URI + "foos").then().assertThat().body(equalTo("Post some Foos")); + } + + @Test + public void givenOneHeader_whenGetFoos_thenOk() { + RestAssured.given().accept("text/html").header("key", "val").get(BASE_URI + "foos").then().assertThat().body(equalTo("Get some Foos with Header")); + } + + @Test + public void givenMultipleHeaders_whenGetFoos_thenOk() { + RestAssured.given().accept("text/html").headers("key1", "val1", "key2", "val2").get(BASE_URI + "foos").then().assertThat().body(equalTo("Get some Foos with Header")); + } + + @Test + public void givenAcceptHeader_whenGetFoos_thenOk() { + RestAssured.given().accept("application/json").get(BASE_URI + "foos").then().assertThat().body(equalTo("Get some Foos with Header New")); + } + + @Test + public void givenPathVariable_whenGetFoos_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "foos/1").then().assertThat().body(equalTo("Get a specific Foo with id=1")); + } + + @Test + public void givenMultiplePathVariable_whenGetFoos_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "foos/1/bar/2").then().assertThat().body(equalTo("Get a specific Bar with id=2 from a Foo with id=1")); + } + + @Test + public void givenPathVariable_whenGetBars_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "bars/1").then().assertThat().body(equalTo("Get a specific Bar with id=1")); + } + + @Test + public void givenParams_whenGetBars_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "bars?id=100&second=something").then().assertThat().body(equalTo("Get a specific Bar with id=100")); + } + + @Test + public void whenGetFoosOrBars_thenOk() { + RestAssured.given().accept("text/html").get(BASE_URI + "advanced/foos").then().assertThat().body(equalTo("Advanced - Get some Foos or Bars")); + RestAssured.given().accept("text/html").get(BASE_URI + "advanced/bars").then().assertThat().body(equalTo("Advanced - Get some Foos or Bars")); + } +} diff --git a/spring-rest/src/test/java/org/baeldung/web/test/SpringHttpMessageConvertersIntegrationTestsCase.java b/spring-rest/src/test/java/org/baeldung/web/test/SpringHttpMessageConvertersIntegrationTestsCase.java index 1536f14bc8..1dfe509c09 100644 --- a/spring-rest/src/test/java/org/baeldung/web/test/SpringHttpMessageConvertersIntegrationTestsCase.java +++ b/spring-rest/src/test/java/org/baeldung/web/test/SpringHttpMessageConvertersIntegrationTestsCase.java @@ -3,9 +3,7 @@ package org.baeldung.web.test; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import org.baeldung.config.converter.KryoHttpMessageConverter; import org.baeldung.web.dto.Foo; @@ -17,11 +15,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter; -import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; -import org.springframework.oxm.xstream.XStreamMarshaller; import org.springframework.web.client.RestTemplate; /** @@ -50,7 +44,6 @@ public class SpringHttpMessageConvertersIntegrationTestsCase { final String URI = BASE_URI + "foos/{id}"; final RestTemplate restTemplate = new RestTemplate(); - restTemplate.setMessageConverters(getMessageConverters()); final HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML)); @@ -67,7 +60,6 @@ public class SpringHttpMessageConvertersIntegrationTestsCase { final String URI = BASE_URI + "foos/{id}"; final RestTemplate restTemplate = new RestTemplate(); - restTemplate.setMessageConverters(getMessageConverters()); final HttpHeaders headers = new HttpHeaders(); headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON)); @@ -83,7 +75,6 @@ public class SpringHttpMessageConvertersIntegrationTestsCase { public void givenConsumingXml_whenWritingTheFoo_thenCorrect() { final String URI = BASE_URI + "foos/{id}"; final RestTemplate restTemplate = new RestTemplate(); - restTemplate.setMessageConverters(getMessageConverters()); final Foo resource = new Foo(4, "jason"); final HttpHeaders headers = new HttpHeaders(); @@ -129,20 +120,4 @@ public class SpringHttpMessageConvertersIntegrationTestsCase { assertThat(resource, notNullValue()); } - // UTIL - - private List> getMessageConverters() { - final List> converters = new ArrayList>(); - - final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter(); - final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller(); - xmlConverter.setMarshaller(xstreamMarshaller); - xmlConverter.setUnmarshaller(xstreamMarshaller); - - converters.add(xmlConverter); - converters.add(new MappingJackson2HttpMessageConverter()); - - return converters; - } - } diff --git a/spring-security-rest-full/src/main/java/org/baeldung/spring/ListenerConfig.java b/spring-security-rest-full/src/main/java/org/baeldung/spring/ListenerConfig.java new file mode 100644 index 0000000000..80af01aeeb --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/spring/ListenerConfig.java @@ -0,0 +1,16 @@ +package org.baeldung.spring; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.springframework.web.WebApplicationInitializer; +import org.springframework.web.context.request.RequestContextListener; + +public class ListenerConfig implements WebApplicationInitializer { + + @Override + public void onStartup(ServletContext sc) throws ServletException { + // Manages the lifecycle of the root application context + sc.addListener(new RequestContextListener()); + } +} \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java b/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java index fa8bdddb4e..57e9b32a62 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/spring/WebConfig.java @@ -1,6 +1,7 @@ package org.baeldung.spring; import org.baeldung.web.interceptor.LoggerInterceptor; +import org.baeldung.web.interceptor.SessionTimerInterceptor; import org.baeldung.web.interceptor.UserInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -15,7 +16,7 @@ import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration @ComponentScan("org.baeldung.web") @EnableWebMvc -public class WebConfig extends WebMvcConfigurerAdapter { +public class WebConfig extends WebMvcConfigurerAdapter{ public WebConfig() { super(); @@ -42,5 +43,7 @@ public class WebConfig extends WebMvcConfigurerAdapter { public void addInterceptors(final InterceptorRegistry registry) { registry.addInterceptor(new LoggerInterceptor()); registry.addInterceptor(new UserInterceptor()); + registry.addInterceptor(new SessionTimerInterceptor()); } + } \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/SessionTimerInterceptor.java b/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/SessionTimerInterceptor.java new file mode 100644 index 0000000000..8d967ed1ef --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/interceptor/SessionTimerInterceptor.java @@ -0,0 +1,57 @@ +package org.baeldung.web.interceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +public class SessionTimerInterceptor extends HandlerInterceptorAdapter { + + private static Logger log = LoggerFactory.getLogger(SessionTimerInterceptor.class); + + private static final long MAX_INACTIVE_SESSION_TIME = 5 * 10000; + + @Autowired + private HttpSession session; + + /** + * Executed before actual handler is executed + **/ + @Override + public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) + throws Exception { + log.info("Pre handle method - check handling start time"); + long startTime = System.currentTimeMillis(); + request.setAttribute("executionTime", startTime); + if (UserInterceptor.isUserLogged()) { + session = request.getSession(); + log.info("Who is logged in: " + SecurityContextHolder.getContext().getAuthentication().getName()); + log.info("Time since last request in this session: " + + (System.currentTimeMillis() - request.getSession().getLastAccessedTime()) + " ms"); + if (System.currentTimeMillis() - session.getLastAccessedTime() > MAX_INACTIVE_SESSION_TIME) { + log.warn("Logging out, due to inactive session"); + SecurityContextHolder.clearContext(); + request.logout(); + response.sendRedirect("/spring-security-rest-full/logout"); + } + } + return true; + } + + /** + * Executed before after handler is executed + **/ + @Override + public void postHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler, + final ModelAndView model) throws Exception { + log.info("Post handle method - check execution time of handling"); + long startTime = (Long) request.getAttribute("executionTime"); + log.info("Execution time for handling the request was: " + (System.currentTimeMillis() - startTime) + " ms"); + } +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorTest.java b/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorTest.java new file mode 100644 index 0000000000..a29de04bb4 --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/web/interceptor/SessionTimerInterceptorTest.java @@ -0,0 +1,56 @@ +package org.baeldung.web.interceptor; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import javax.servlet.http.HttpSession; + +import org.baeldung.spring.PersistenceConfig; +import org.baeldung.spring.SecurityWithoutCsrfConfig; +import org.baeldung.spring.WebConfig; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mock.web.MockHttpSession; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.context.WebApplicationContext; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +@Transactional +@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) +@WithMockUser(username = "admin", roles = { "USER", "ADMIN" }) +public class SessionTimerInterceptorTest { + + @Autowired + WebApplicationContext wac; + + private MockMvc mockMvc; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); + } + + /** + * After execution of HTTP GET logs from interceptor will be displayed in + * the console + */ + @Test + public void testInterceptors() throws Exception { + HttpSession session = mockMvc.perform(get("/auth/admin")).andExpect(status().is2xxSuccessful()).andReturn() + .getRequest().getSession(); + Thread.sleep(51000); + mockMvc.perform(get("/auth/admin").session((MockHttpSession) session)).andExpect(status().is2xxSuccessful()); + } + +}