diff --git a/core-java-8/src/main/java/com/baeldung/AdderImpl.java b/core-java-8/src/main/java/com/baeldung/AdderImpl.java index 5109f3aaba..f67cdc26b3 100644 --- a/core-java-8/src/main/java/com/baeldung/AdderImpl.java +++ b/core-java-8/src/main/java/com/baeldung/AdderImpl.java @@ -6,12 +6,12 @@ import java.util.function.Function; public class AdderImpl implements Adder { @Override - public String addWithFunction(Function f) { + public String addWithFunction(final Function f) { return f.apply("Something "); } @Override - public void addWithConsumer(Consumer f) { + public void addWithConsumer(final Consumer f) { } } diff --git a/core-java-8/src/main/java/com/baeldung/doublecolon/Computer.java b/core-java-8/src/main/java/com/baeldung/doublecolon/Computer.java new file mode 100644 index 0000000000..b5d2e70abd --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/doublecolon/Computer.java @@ -0,0 +1,88 @@ +package com.baeldung.doublecolon; + +public class Computer { + + private Integer age; + private String color; + private Integer healty; + + public Computer(final int age, final String color) { + this.age = age; + this.color = color; + } + + public Computer(final Integer age, final String color, final Integer healty) { + this.age = age; + this.color = color; + this.healty = healty; + } + + public Computer() { + } + + public Integer getAge() { + return age; + } + + public void setAge(final Integer age) { + this.age = age; + } + + public String getColor() { + return color; + } + + public void setColor(final String color) { + this.color = color; + } + + public Integer getHealty() { + return healty; + } + + public void setHealty(final Integer healty) { + this.healty = healty; + } + + public void turnOnPc() { + System.out.println("Computer turned on"); + } + + public void turnOffPc() { + System.out.println("Computer turned off"); + } + + public Double calculateValue(Double initialValue) { + return initialValue / 1.50; + } + + @Override + public String toString() { + return "Computer{" + "age=" + age + ", color='" + color + '\'' + ", healty=" + healty + '}'; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + final Computer computer = (Computer) o; + + if (age != null ? !age.equals(computer.age) : computer.age != null) { + return false; + } + return color != null ? color.equals(computer.color) : computer.color == null; + + } + + @Override + public int hashCode() { + int result = age != null ? age.hashCode() : 0; + result = 31 * result + (color != null ? color.hashCode() : 0); + return result; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/doublecolon/ComputerUtils.java b/core-java-8/src/main/java/com/baeldung/doublecolon/ComputerUtils.java new file mode 100644 index 0000000000..d181dfcdf7 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/doublecolon/ComputerUtils.java @@ -0,0 +1,27 @@ +package com.baeldung.doublecolon; + +import com.baeldung.doublecolon.function.ComputerPredicate; + +import java.util.ArrayList; +import java.util.List; + +public class ComputerUtils { + + public static final ComputerPredicate after2010Predicate = (c) -> (c.getAge() > 2010); + public static final ComputerPredicate blackPredicate = (c) -> "black".equals(c.getColor()); + + public static List filter(final List inventory, final ComputerPredicate p) { + + final List result = new ArrayList<>(); + inventory.stream().filter(p::filter).forEach(result::add); + + return result; + } + + public static void repair(final Computer computer) { + if (computer.getHealty() < 50) { + computer.setHealty(100); + } + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/doublecolon/MacbookPro.java b/core-java-8/src/main/java/com/baeldung/doublecolon/MacbookPro.java new file mode 100644 index 0000000000..3fc459c681 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/doublecolon/MacbookPro.java @@ -0,0 +1,34 @@ +package com.baeldung.doublecolon; + +import java.util.function.Function; + +public class MacbookPro extends Computer { + + public MacbookPro(int age, String color) { + super(age, color); + } + + public MacbookPro(Integer age, String color, Integer healty) { + super(age, color, healty); + } + + @Override + public void turnOnPc() { + System.out.println("MacbookPro turned on"); + } + + @Override + public void turnOffPc() { + System.out.println("MacbookPro turned off"); + } + + @Override + public Double calculateValue(Double initialValue) { + + Function function = super::calculateValue; + final Double pcValue = function.apply(initialValue); + System.out.println("First value is:" + pcValue); + return pcValue + (initialValue / 10); + + } +} diff --git a/core-java-8/src/main/java/com/baeldung/doublecolon/function/ComputerPredicate.java b/core-java-8/src/main/java/com/baeldung/doublecolon/function/ComputerPredicate.java new file mode 100644 index 0000000000..5ce491e86a --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/doublecolon/function/ComputerPredicate.java @@ -0,0 +1,10 @@ +package com.baeldung.doublecolon.function; + +import com.baeldung.doublecolon.Computer; + +@FunctionalInterface +public interface ComputerPredicate { + + boolean filter(Computer c); + +} diff --git a/core-java-8/src/main/java/com/baeldung/doublecolon/function/TriFunction.java b/core-java-8/src/main/java/com/baeldung/doublecolon/function/TriFunction.java new file mode 100644 index 0000000000..d0d6299479 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/doublecolon/function/TriFunction.java @@ -0,0 +1,15 @@ +package com.baeldung.doublecolon.function; + +import java.util.Objects; +import java.util.function.Function; + +@FunctionalInterface +public interface TriFunction { + + R apply(A a, B b, C c); + + default TriFunction andThen(final Function after) { + Objects.requireNonNull(after); + return (final A a, final B b, final C c) -> after.apply(apply(a, b, c)); + } +} \ No newline at end of file diff --git a/core-java-8/src/test/java/com/baeldung/doublecolon/TestComputerUtils.java b/core-java-8/src/test/java/com/baeldung/doublecolon/TestComputerUtils.java new file mode 100644 index 0000000000..5ae6f02a56 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/doublecolon/TestComputerUtils.java @@ -0,0 +1,89 @@ +package com.baeldung.doublecolon; + +import com.baeldung.doublecolon.function.TriFunction; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.*; +import java.util.function.BiFunction; + +import static com.baeldung.doublecolon.ComputerUtils.*; + +public class TestComputerUtils { + + @Before + public void setup() { + } + + @After + public void tearDown() { + } + + @Test + public void testConstructorReference() { + + Computer c1 = new Computer(2015, "white"); + Computer c2 = new Computer(2009, "black"); + Computer c3 = new Computer(2014, "black"); + + BiFunction c4Function = Computer::new; + Computer c4 = c4Function.apply(2013, "white"); + BiFunction c5Function = Computer::new; + Computer c5 = c5Function.apply(2010, "black"); + BiFunction c6Function = Computer::new; + Computer c6 = c6Function.apply(2008, "black"); + + List inventory = Arrays.asList(c1, c2, c3, c4, c5, c6); + + List blackComputer = filter(inventory, blackPredicate); + Assert.assertEquals("The black Computers are: ", blackComputer.size(), 4); + + List after2010Computer = filter(inventory, after2010Predicate); + Assert.assertEquals("The Computer bought after 2010 are: ", after2010Computer.size(), 3); + + List before2011Computer = filter(inventory, c -> c.getAge() < 2011); + Assert.assertEquals("The Computer bought before 2011 are: ", before2011Computer.size(), 3); + + inventory.sort(Comparator.comparing(Computer::getAge)); + + Assert.assertEquals("Oldest Computer in inventory", c6, inventory.get(0)); + + } + + @Test + public void testStaticMethodReference() { + + Computer c1 = new Computer(2015, "white", 35); + Computer c2 = new Computer(2009, "black", 65); + TriFunction c6Function = Computer::new; + Computer c3 = c6Function.apply(2008, "black", 90); + + List inventory = Arrays.asList(c1, c2, c3); + inventory.forEach(ComputerUtils::repair); + + Assert.assertEquals("Computer repaired", new Integer(100), c1.getHealty()); + } + + @Test + public void testInstanceMethodArbitraryObjectParticularType() { + + Computer c1 = new Computer(2015, "white", 35); + Computer c2 = new MacbookPro(2009, "black", 65); + List inventory = Arrays.asList(c1, c2); + inventory.forEach(Computer::turnOnPc); + + } + + @Test + public void testSuperMethodReference() { + + final TriFunction integerStringIntegerObjectTriFunction = MacbookPro::new; + final MacbookPro macbookPro = integerStringIntegerObjectTriFunction.apply(2010, "black", 100); + Double initialValue = new Double(999.99); + final Double actualValue = macbookPro.calculateValue(initialValue); + Assert.assertEquals(766.659, actualValue, 0.0); + } + +} diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java index 7329a2dc97..9c248ad8ce 100644 --- a/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java @@ -30,6 +30,14 @@ public class Java8CollectionCleanupUnitTest { assertThat(listWithoutNulls, hasSize(3)); } + @Test + public void givenListContainsNulls_whenRemovingNullsWithRemoveIf_thenCorrect() { + final List listWithoutNulls = Lists.newArrayList(null, 1, 2, null, 3, null); + listWithoutNulls.removeIf(p -> p == null); + + assertThat(listWithoutNulls, hasSize(3)); + } + @Test public void givenListContainsDuplicates_whenRemovingDuplicatesWithJava8_thenCorrect() { final List listWithDuplicates = Lists.newArrayList(1, 1, 2, 2, 3, 3); diff --git a/guava/src/test/java/org/baeldung/java/CollectionJavaPartitionUnitTest.java b/guava/src/test/java/org/baeldung/java/CollectionJavaPartitionUnitTest.java new file mode 100644 index 0000000000..63583987ea --- /dev/null +++ b/guava/src/test/java/org/baeldung/java/CollectionJavaPartitionUnitTest.java @@ -0,0 +1,70 @@ +package org.baeldung.java; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import org.junit.Test; + +import com.google.common.collect.Lists; + +public class CollectionJavaPartitionUnitTest { + + // java8 groupBy + @Test + public final void givenList_whenParitioningIntoNSublistsUsingGroupingBy_thenCorrect() { + final List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); + + final Map> groups = intList.stream().collect(Collectors.groupingBy(s -> (s - 1) / 3)); + final List> subSets = new ArrayList>(groups.values()); + + // When + final List lastPartition = subSets.get(2); + final List expectedLastPartition = Lists. newArrayList(7, 8); + assertThat(subSets.size(), equalTo(3)); + assertThat(lastPartition, equalTo(expectedLastPartition)); + + // intList.add(9); + // System.out.println(groups.values()); + } + + // java8 partitionBy + @Test + public final void givenList_whenParitioningIntoSublistsUsingPartitionBy_thenCorrect() { + final List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); + + final Map> groups = intList.stream().collect(Collectors.partitioningBy(s -> s > 6)); + final List> subSets = new ArrayList>(groups.values()); + + // When + final List lastPartition = subSets.get(1); + final List expectedLastPartition = Lists. newArrayList(7, 8); + assertThat(subSets.size(), equalTo(2)); + assertThat(lastPartition, equalTo(expectedLastPartition)); + + // intList.add(9); + // System.out.println(groups.values()); + } + + // java8 split by separator + @Test + public final void givenList_whenSplittingBySeparator_thenCorrect() { + final List intList = Lists.newArrayList(1, 2, 3, 0, 4, 5, 6, 0, 7, 8); + + final int[] indexes = Stream.of(IntStream.of(-1), IntStream.range(0, intList.size()).filter(i -> intList.get(i) == 0), IntStream.of(intList.size())).flatMapToInt(s -> s).toArray(); + final List> subSets = IntStream.range(0, indexes.length - 1).mapToObj(i -> intList.subList(indexes[i] + 1, indexes[i + 1])).collect(Collectors.toList()); + + // When + final List lastPartition = subSets.get(2); + final List expectedLastPartition = Lists. newArrayList(7, 8); + assertThat(subSets.size(), equalTo(3)); + assertThat(lastPartition, equalTo(expectedLastPartition)); + } + +} diff --git a/jackson/src/main/resources/node_example.json b/jackson/src/main/resources/node_example.json new file mode 100644 index 0000000000..69d37efbf6 --- /dev/null +++ b/jackson/src/main/resources/node_example.json @@ -0,0 +1,10 @@ +{ + "name": + { + "first": "Tatu", + "last": "Saloranta" + }, + + "title": "Jackson founder", + "company": "FasterXML" +} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/node/ExampleStructure.java b/jackson/src/test/java/org/baeldung/jackson/node/ExampleStructure.java new file mode 100644 index 0000000000..0eb15f3bb8 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/node/ExampleStructure.java @@ -0,0 +1,17 @@ +package org.baeldung.jackson.node; + +import java.io.IOException; +import java.io.InputStream; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class ExampleStructure { + private static ObjectMapper mapper = new ObjectMapper(); + + static JsonNode getExampleRoot() throws IOException { + InputStream exampleInput = ExampleStructure.class.getClassLoader().getResourceAsStream("node_example.json"); + JsonNode rootNode = mapper.readTree(exampleInput); + return rootNode; + } +} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/node/NodeBean.java b/jackson/src/test/java/org/baeldung/jackson/node/NodeBean.java new file mode 100644 index 0000000000..7d54a6140e --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/node/NodeBean.java @@ -0,0 +1,30 @@ +package org.baeldung.jackson.node; + +public class NodeBean { + private int id; + private String name; + + public NodeBean() { + } + + public NodeBean(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/node/NodeOperationTest.java b/jackson/src/test/java/org/baeldung/jackson/node/NodeOperationTest.java new file mode 100644 index 0000000000..c1398b2165 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/node/NodeOperationTest.java @@ -0,0 +1,103 @@ +package org.baeldung.jackson.node; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +public class NodeOperationTest { + private static ObjectMapper mapper = new ObjectMapper(); + + @Test + public void givenAnObject_whenConvertingIntoNode_thenCorrect() { + final NodeBean fromValue = new NodeBean(2016, "baeldung.com"); + + final JsonNode node = mapper.valueToTree(fromValue); + + assertEquals(2016, node.get("id").intValue()); + assertEquals("baeldung.com", node.get("name").textValue()); + } + + @Test + public void givenANode_whenWritingOutAsAJsonString_thenCorrect() throws IOException { + final String pathToTestFile = "node_to_json_test.json"; + final char[] characterBuffer = new char[50]; + + final JsonNode node = mapper.createObjectNode(); + ((ObjectNode) node).put("id", 2016); + ((ObjectNode) node).put("name", "baeldung.com"); + + try (FileWriter outputStream = new FileWriter(pathToTestFile)) { + mapper.writeValue(outputStream, node); + } + + try (FileReader inputStreamForAssertion = new FileReader(pathToTestFile)) { + inputStreamForAssertion.read(characterBuffer); + } + final String textContentOfTestFile = new String(characterBuffer); + + assertThat(textContentOfTestFile, containsString("2016")); + assertThat(textContentOfTestFile, containsString("baeldung.com")); + + Files.delete(Paths.get(pathToTestFile)); + } + + @Test + public void givenANode_whenConvertingIntoAnObject_thenCorrect() throws JsonProcessingException { + final JsonNode node = mapper.createObjectNode(); + ((ObjectNode) node).put("id", 2016); + ((ObjectNode) node).put("name", "baeldung.com"); + + final NodeBean toValue = mapper.treeToValue(node, NodeBean.class); + + assertEquals(2016, toValue.getId()); + assertEquals("baeldung.com", toValue.getName()); + } + + @Test + public void givenANode_whenAddingIntoATree_thenCorrect() throws IOException { + final JsonNode rootNode = ExampleStructure.getExampleRoot(); + final ObjectNode addedNode = ((ObjectNode) rootNode).putObject("address"); + addedNode.put("city", "Seattle").put("state", "Washington").put("country", "United States"); + + assertFalse(rootNode.path("address").isMissingNode()); + assertEquals("Seattle", rootNode.path("address").path("city").textValue()); + assertEquals("Washington", rootNode.path("address").path("state").textValue()); + assertEquals("United States", rootNode.path("address").path("country").textValue()); + } + + @Test + public void givenANode_whenModifyingIt_thenCorrect() throws IOException { + final String newString = "{\"nick\": \"cowtowncoder\"}"; + final JsonNode newNode = mapper.readTree(newString); + + final JsonNode rootNode = ExampleStructure.getExampleRoot(); + ((ObjectNode) rootNode).set("name", newNode); + + assertFalse(rootNode.path("name").path("nick").isMissingNode()); + assertEquals("cowtowncoder", rootNode.path("name").path("nick").textValue()); + } + + @Test + public void givenANode_whenRemovingFromATree_thenCorrect() throws IOException { + final JsonNode rootNode = ExampleStructure.getExampleRoot(); + ((ObjectNode) rootNode).remove("company"); + + assertTrue(rootNode.path("company").isMissingNode()); + } + +} diff --git a/mockito-mocks-spring-beans/.gitignore b/mockito-mocks-spring-beans/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/mockito-mocks-spring-beans/.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/mockito-mocks-spring-beans/pom.xml b/mockito-mocks-spring-beans/pom.xml new file mode 100644 index 0000000000..64dc7d83c9 --- /dev/null +++ b/mockito-mocks-spring-beans/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + + com.baeldung + mockito-mocks-spring-beans + 0.0.1-SNAPSHOT + jar + + mocks + Injecting Mockito Mocks into Spring Beans + + + org.springframework.boot + spring-boot-starter-parent + 1.3.1.RELEASE + + + + + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + 1.3.1.RELEASE + + + org.springframework.boot + spring-boot-starter-test + 1.3.1.RELEASE + test + + + org.mockito + mockito-all + 1.10.19 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/mockito-mocks-spring-beans/src/main/java/com/baeldung/MocksApplication.java b/mockito-mocks-spring-beans/src/main/java/com/baeldung/MocksApplication.java new file mode 100644 index 0000000000..32be4c6a0a --- /dev/null +++ b/mockito-mocks-spring-beans/src/main/java/com/baeldung/MocksApplication.java @@ -0,0 +1,11 @@ +package com.baeldung; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MocksApplication { + public static void main(String[] args) { + SpringApplication.run(MocksApplication.class, args); + } +} diff --git a/mockito-mocks-spring-beans/src/main/java/com/baeldung/NameService.java b/mockito-mocks-spring-beans/src/main/java/com/baeldung/NameService.java new file mode 100644 index 0000000000..bc328cfd8a --- /dev/null +++ b/mockito-mocks-spring-beans/src/main/java/com/baeldung/NameService.java @@ -0,0 +1,10 @@ +package com.baeldung; + +import org.springframework.stereotype.Service; + +@Service +public class NameService { + public String getUserName(String id) { + return "Real user name"; + } +} diff --git a/mockito-mocks-spring-beans/src/main/java/com/baeldung/UserService.java b/mockito-mocks-spring-beans/src/main/java/com/baeldung/UserService.java new file mode 100644 index 0000000000..fe7e35b9f8 --- /dev/null +++ b/mockito-mocks-spring-beans/src/main/java/com/baeldung/UserService.java @@ -0,0 +1,19 @@ +package com.baeldung; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class UserService { + + private NameService nameService; + + @Autowired + public UserService(NameService nameService) { + this.nameService = nameService; + } + + public String getUserName(String id) { + return nameService.getUserName(id); + } +} diff --git a/mockito-mocks-spring-beans/src/main/resources/application.properties b/mockito-mocks-spring-beans/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mockito-mocks-spring-beans/src/test/java/com/baeldung/NameServiceTestConfiguration.java b/mockito-mocks-spring-beans/src/test/java/com/baeldung/NameServiceTestConfiguration.java new file mode 100644 index 0000000000..2c63ff6203 --- /dev/null +++ b/mockito-mocks-spring-beans/src/test/java/com/baeldung/NameServiceTestConfiguration.java @@ -0,0 +1,17 @@ +package com.baeldung; + +import org.mockito.Mockito; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; + +@Profile("test") +@Configuration +public class NameServiceTestConfiguration { + @Bean + @Primary + public NameService nameService() { + return Mockito.mock(NameService.class); + } +} diff --git a/mockito-mocks-spring-beans/src/test/java/com/baeldung/UserServiceTest.java b/mockito-mocks-spring-beans/src/test/java/com/baeldung/UserServiceTest.java new file mode 100644 index 0000000000..631a8634be --- /dev/null +++ b/mockito-mocks-spring-beans/src/test/java/com/baeldung/UserServiceTest.java @@ -0,0 +1,31 @@ +package com.baeldung; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ActiveProfiles("test") +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = MocksApplication.class) +public class UserServiceTest { + + @Autowired + private UserService userService; + + @Autowired + private NameService nameService; + + @Test + public void whenUserIdIsProvided_thenRetrievedNameIsCorrect() { + Mockito.when(nameService.getUserName("SomeId")).thenReturn("Mock user name"); + + String testName = userService.getUserName("SomeId"); + + Assert.assertEquals("Mock user name", testName); + } +} \ No newline at end of file diff --git a/spring-all/src/main/java/org/baeldung/customannotation/DataAccess.java b/spring-all/src/main/java/org/baeldung/customannotation/DataAccess.java index 11bc30a84a..9a8a493a6d 100644 --- a/spring-all/src/main/java/org/baeldung/customannotation/DataAccess.java +++ b/spring-all/src/main/java/org/baeldung/customannotation/DataAccess.java @@ -10,5 +10,5 @@ import java.lang.annotation.Target; @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @Documented public @interface DataAccess { - Classentity(); + Class entity(); } diff --git a/spring-all/src/main/java/org/baeldung/customannotation/DataAccessAnnotationProcessor.java b/spring-all/src/main/java/org/baeldung/customannotation/DataAccessAnnotationProcessor.java index 7902da746e..c792073745 100644 --- a/spring-all/src/main/java/org/baeldung/customannotation/DataAccessAnnotationProcessor.java +++ b/spring-all/src/main/java/org/baeldung/customannotation/DataAccessAnnotationProcessor.java @@ -19,15 +19,13 @@ public class DataAccessAnnotationProcessor implements BeanPostProcessor { } @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { scanDataAccessAnnotation(bean, beanName); return bean; } @Override - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } diff --git a/spring-all/src/main/java/org/baeldung/customannotation/DataAccessFieldCallback.java b/spring-all/src/main/java/org/baeldung/customannotation/DataAccessFieldCallback.java index 16526fa56f..8cb62affc4 100644 --- a/spring-all/src/main/java/org/baeldung/customannotation/DataAccessFieldCallback.java +++ b/spring-all/src/main/java/org/baeldung/customannotation/DataAccessFieldCallback.java @@ -12,18 +12,14 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils.FieldCallback; - public final class DataAccessFieldCallback implements FieldCallback { private static Logger logger = LoggerFactory.getLogger(DataAccessFieldCallback.class); private static int AUTOWIRE_MODE = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME; - private static String ERROR_ENTITY_VALUE_NOT_SAME = "@DataAccess(entity) " - + "value should have same type with injected generic type."; - private static String WARN_NON_GENERIC_VALUE = "@DataAccess annotation assigned " - + "to raw (non-generic) declaration. This will make your code less type-safe."; - private static String ERROR_CREATE_INSTANCE = "Cannot create instance of " - + "type '{}' or instance creation is failed because: {}"; + private static String ERROR_ENTITY_VALUE_NOT_SAME = "@DataAccess(entity) " + "value should have same type with injected generic type."; + private static String WARN_NON_GENERIC_VALUE = "@DataAccess annotation assigned " + "to raw (non-generic) declaration. This will make your code less type-safe."; + private static String ERROR_CREATE_INSTANCE = "Cannot create instance of " + "type '{}' or instance creation is failed because: {}"; private ConfigurableListableBeanFactory configurableListableBeanFactory; private Object bean; @@ -34,15 +30,14 @@ public final class DataAccessFieldCallback implements FieldCallback { } @Override - public void doWith(final Field field) - throws IllegalArgumentException, IllegalAccessException { + public void doWith(final Field field) throws IllegalArgumentException, IllegalAccessException { if (!field.isAnnotationPresent(DataAccess.class)) { return; } ReflectionUtils.makeAccessible(field); final Type fieldGenericType = field.getGenericType(); - // In this example, get actual "GenericDAO' type. - final Class generic = field.getType(); + // In this example, get actual "GenericDAO' type. + final Class generic = field.getType(); final Class classValue = field.getDeclaredAnnotation(DataAccess.class).entity(); if (genericTypeIsValid(classValue, fieldGenericType)) { @@ -54,7 +49,6 @@ public final class DataAccessFieldCallback implements FieldCallback { } } - /** * For example, if user write: *
@@ -75,8 +69,6 @@ public final class DataAccessFieldCallback implements FieldCallback {
         }
     }
 
-
-
     public final Object getBeanInstance(final String beanName, final Class genericClass, final Class paramClass) {
         Object daoInstance = null;
         if (!configurableListableBeanFactory.containsBean(beanName)) {
@@ -90,7 +82,7 @@ public final class DataAccessFieldCallback implements FieldCallback {
                 logger.error(ERROR_CREATE_INSTANCE, genericClass.getTypeName(), e);
                 throw new RuntimeException(e);
             }
-            
+
             daoInstance = configurableListableBeanFactory.initializeBean(toRegister, beanName);
             configurableListableBeanFactory.autowireBeanProperties(daoInstance, AUTOWIRE_MODE, true);
             configurableListableBeanFactory.registerSingleton(beanName, daoInstance);
diff --git a/spring-all/src/test/java/org/baeldung/customannotation/BeanWithGenericDAO.java b/spring-all/src/test/java/org/baeldung/customannotation/BeanWithGenericDAO.java
index 32d4660f41..9ba915f296 100644
--- a/spring-all/src/test/java/org/baeldung/customannotation/BeanWithGenericDAO.java
+++ b/spring-all/src/test/java/org/baeldung/customannotation/BeanWithGenericDAO.java
@@ -5,10 +5,11 @@ import org.springframework.stereotype.Repository;
 @Repository
 public class BeanWithGenericDAO {
 
-    @DataAccess(entity=Person.class)
+    @DataAccess(entity = Person.class)
     private GenericDAO personGenericDAO;
 
-    public BeanWithGenericDAO() {}
+    public BeanWithGenericDAO() {
+    }
 
     public GenericDAO getPersonGenericDAO() {
         return personGenericDAO;
diff --git a/spring-all/src/test/java/org/baeldung/customannotation/DataAccessFieldCallbackTest.java b/spring-all/src/test/java/org/baeldung/customannotation/DataAccessFieldCallbackTest.java
index f025a3e00a..e47d03c961 100644
--- a/spring-all/src/test/java/org/baeldung/customannotation/DataAccessFieldCallbackTest.java
+++ b/spring-all/src/test/java/org/baeldung/customannotation/DataAccessFieldCallbackTest.java
@@ -15,7 +15,6 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
-
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration(classes = { CustomAnnotationConfiguration.class })
 public class DataAccessFieldCallbackTest {
@@ -36,8 +35,7 @@ public class DataAccessFieldCallbackTest {
     }
 
     @Test
-    public void whenMethodGenericTypeIsValidCalled_thenReturnCorrectValue()
-            throws NoSuchFieldException, SecurityException {
+    public void whenMethodGenericTypeIsValidCalled_thenReturnCorrectValue() throws NoSuchFieldException, SecurityException {
         final DataAccessFieldCallback callback = new DataAccessFieldCallback(configurableListableBeanFactory, beanWithGenericDAO);
         final Type fieldType = BeanWithGenericDAO.class.getDeclaredField("personGenericDAO").getGenericType();
         final boolean result = callback.genericTypeIsValid(Person.class, fieldType);
diff --git a/spring-batch/README.md b/spring-batch/README.md
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/spring-batch/README.md
@@ -0,0 +1 @@
+
diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringBatchConfig.java b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringBatchConfig.java
index a024cbc04e..9973005c7c 100644
--- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringBatchConfig.java
+++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringBatchConfig.java
@@ -40,8 +40,7 @@ public class SpringBatchConfig {
     private Resource outputXml;
 
     @Bean
-    public ItemReader itemReader()
-        throws UnexpectedInputException, ParseException {
+    public ItemReader itemReader() throws UnexpectedInputException, ParseException {
         FlatFileItemReader reader = new FlatFileItemReader();
         DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
         String[] tokens = { "username", "userid", "transactiondate", "amount" };
@@ -61,8 +60,7 @@ public class SpringBatchConfig {
     }
 
     @Bean
-    public ItemWriter itemWriter(Marshaller marshaller)
-        throws MalformedURLException {
+    public ItemWriter itemWriter(Marshaller marshaller) throws MalformedURLException {
         StaxEventItemWriter itemWriter = new StaxEventItemWriter();
         itemWriter.setMarshaller(marshaller);
         itemWriter.setRootTagName("transactionRecord");
@@ -78,11 +76,8 @@ public class SpringBatchConfig {
     }
 
     @Bean
-    protected Step step1(ItemReader reader,
-        ItemProcessor processor,
-        ItemWriter writer) {
-        return steps.get("step1"). chunk(10)
-            .reader(reader).processor(processor).writer(writer).build();
+    protected Step step1(ItemReader reader, ItemProcessor processor, ItemWriter writer) {
+        return steps.get("step1"). chunk(10).reader(reader).processor(processor).writer(writer).build();
     }
 
     @Bean(name = "firstBatchJob")
diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringConfig.java b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringConfig.java
index 91366d8721..ed7d302047 100644
--- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringConfig.java
+++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringConfig.java
@@ -38,8 +38,7 @@ public class SpringConfig {
     }
 
     @Bean
-    public DataSourceInitializer dataSourceInitializer(DataSource dataSource)
-        throws MalformedURLException {
+    public DataSourceInitializer dataSourceInitializer(DataSource dataSource) throws MalformedURLException {
         ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
 
         databasePopulator.addScript(dropReopsitoryTables);
diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/model/Transaction.java b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/model/Transaction.java
index 6e80298ff0..3b2b9610f2 100644
--- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/model/Transaction.java
+++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/model/Transaction.java
@@ -48,9 +48,7 @@ public class Transaction {
 
     @Override
     public String toString() {
-        return "Transaction [username=" + username + ", userId=" + userId
-            + ", transactionDate=" + transactionDate + ", amount=" + amount
-            + "]";
+        return "Transaction [username=" + username + ", userId=" + userId + ", transactionDate=" + transactionDate + ", amount=" + amount + "]";
     }
 
 }
diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/CustomItemProcessor.java b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/CustomItemProcessor.java
index baabe79409..ebee1d2802 100644
--- a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/CustomItemProcessor.java
+++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/CustomItemProcessor.java
@@ -3,8 +3,7 @@ package org.baeldung.spring_batch_intro.service;
 import org.baeldung.spring_batch_intro.model.Transaction;
 import org.springframework.batch.item.ItemProcessor;
 
-public class CustomItemProcessor implements
-    ItemProcessor {
+public class CustomItemProcessor implements ItemProcessor {
 
     public Transaction process(Transaction item) {
         System.out.println("Processing..." + item);
diff --git a/spring-data-cassandra/pom.xml b/spring-data-cassandra/pom.xml
index b2b649a422..7e21859b5d 100644
--- a/spring-data-cassandra/pom.xml
+++ b/spring-data-cassandra/pom.xml
@@ -11,8 +11,11 @@
 
 	
 		UTF-8
+        
+		4.2.3.RELEASE
+        
 		1.3.2.RELEASE
-		4.2.2.RELEASE
+        
 		4.11
 		1.7.12
 		1.1.3
diff --git a/spring-data-mongodb/.project b/spring-data-mongodb/.project
index e3d7687573..2e5a0d4bac 100644
--- a/spring-data-mongodb/.project
+++ b/spring-data-mongodb/.project
@@ -11,12 +11,12 @@
 			
 		
 		
-			org.eclipse.m2e.core.maven2Builder
+			org.springframework.ide.eclipse.core.springbuilder
 			
 			
 		
 		
-			org.springframework.ide.eclipse.core.springbuilder
+			org.eclipse.m2e.core.maven2Builder
 			
 			
 		
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 23ac353350..558af930b3 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -117,9 +117,11 @@
 
     
         UTF-8
+        
+        4.2.4.RELEASE
 
         1.7.1.RELEASE
-        4.2.2.RELEASE
+
         1.3
         4.11
         2.4.1
diff --git a/spring-data-mongodb/src/main/java/org/baeldung/converter/UserWriterConverter.java b/spring-data-mongodb/src/main/java/org/baeldung/converter/UserWriterConverter.java
index 54fa78e2d0..2dedda46ec 100644
--- a/spring-data-mongodb/src/main/java/org/baeldung/converter/UserWriterConverter.java
+++ b/spring-data-mongodb/src/main/java/org/baeldung/converter/UserWriterConverter.java
@@ -9,6 +9,7 @@ import com.mongodb.DBObject;
 
 @Component
 public class UserWriterConverter implements Converter {
+
     @Override
     public DBObject convert(final User user) {
         final DBObject dbObject = new BasicDBObject();
@@ -22,4 +23,5 @@ public class UserWriterConverter implements Converter {
         dbObject.removeField("_class");
         return dbObject;
     }
+
 }
diff --git a/spring-data-redis/README.md b/spring-data-redis/README.md
new file mode 100644
index 0000000000..b9b2e5d93d
--- /dev/null
+++ b/spring-data-redis/README.md
@@ -0,0 +1,15 @@
+## Spring Data Redis
+
+### Relevant Articles:
+- [Introduction to Spring Data Redis]
+
+### Build the Project with Tests Running
+```
+mvn clean install
+```
+
+### Run Tests Directly
+```
+mvn test
+```
+
diff --git a/spring-data-redis/pom.xml b/spring-data-redis/pom.xml
new file mode 100644
index 0000000000..98da69934c
--- /dev/null
+++ b/spring-data-redis/pom.xml
@@ -0,0 +1,76 @@
+
+  4.0.0
+
+  org.baeldung
+  sprint-data-redis
+  0.0.1-SNAPSHOT
+  jar
+
+  
+    UTF-8
+    4.2.2.RELEASE
+    1.6.2.RELEASE
+    0.8.0
+  
+
+  
+    
+      org.springframework.data
+      spring-data-redis
+      ${spring-data-redis}
+    
+
+    
+      cglib
+      cglib-nodep
+      2.2
+    
+
+    
+      log4j
+      log4j
+      1.2.16
+    
+
+    
+      redis.clients
+      jedis
+      2.5.1
+      jar
+    
+
+    
+      org.springframework
+      spring-core
+      ${spring.version}
+    
+
+    
+      org.springframework
+      spring-context
+      ${spring.version}
+    
+
+    
+      junit
+      junit
+      4.12
+      test
+    
+
+    
+      org.springframework
+      spring-test
+      ${spring.version}
+      test
+    
+
+    
+      com.lordofthejars
+      nosqlunit-redis
+      ${nosqlunit.version}
+    
+
+  
+
diff --git a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/config/RedisConfig.java b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/config/RedisConfig.java
new file mode 100644
index 0000000000..a7e75a438a
--- /dev/null
+++ b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/config/RedisConfig.java
@@ -0,0 +1,24 @@
+package org.baeldung.spring.data.redis.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+
+@Configuration
+@ComponentScan("org.baeldung.spring.data.redis")
+public class RedisConfig {
+
+    @Bean
+    JedisConnectionFactory jedisConnectionFactory() {
+        return new JedisConnectionFactory();
+    }
+
+    @Bean
+    public RedisTemplate redisTemplate() {
+        final RedisTemplate< String, Object> template =  new RedisTemplate();
+        template.setConnectionFactory(jedisConnectionFactory());
+        return template;
+    }
+}
diff --git a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/model/Student.java b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/model/Student.java
new file mode 100644
index 0000000000..acc96899ce
--- /dev/null
+++ b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/model/Student.java
@@ -0,0 +1,59 @@
+package org.baeldung.spring.data.redis.model;
+
+import java.io.Serializable;
+
+public class Student implements Serializable {
+
+    public enum Gender {
+        MALE, FEMALE
+    }
+
+    private String id;
+    private String name;
+    private Gender gender;
+    private int grade;
+
+    public Student(String id, String name, Gender gender, int grade) {
+        this.id = id;
+        this.name = name;
+        this.gender = gender;
+        this.grade = grade;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Gender getGender() {
+        return gender;
+    }
+
+    public void setGender(Gender gender) {
+        this.gender = gender;
+    }
+
+    public int getGrade() {
+        return grade;
+    }
+
+    public void setGrade(int grade) {
+        this.grade = grade;
+    }
+
+    @Override
+    public String toString() {
+        return "Student{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", gender=" + gender + ", grade=" + grade + '}';
+    }
+}
\ No newline at end of file
diff --git a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepository.java b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepository.java
new file mode 100644
index 0000000000..9e5502f8e0
--- /dev/null
+++ b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepository.java
@@ -0,0 +1,20 @@
+package org.baeldung.spring.data.redis.repo;
+
+import org.baeldung.spring.data.redis.model.Student;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+public interface StudentRepository {
+
+    void saveStudent(Student person);
+    
+    void updateStudent(Student student);
+
+    Student findStudent(String id);
+
+    Map findAllStudents();
+
+    void deleteStudent(String id);
+}
diff --git a/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepositoryImpl.java b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepositoryImpl.java
new file mode 100644
index 0000000000..43294cae58
--- /dev/null
+++ b/spring-data-redis/src/main/java/org/baeldung/spring/data/redis/repo/StudentRepositoryImpl.java
@@ -0,0 +1,49 @@
+package org.baeldung.spring.data.redis.repo;
+
+import org.baeldung.spring.data.redis.model.Student;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Repository;
+
+import javax.annotation.PostConstruct;
+import java.util.Map;
+
+@Repository
+public class StudentRepositoryImpl implements StudentRepository {
+
+    private static final String KEY = "Student";
+
+    private RedisTemplate redisTemplate;
+    private HashOperations hashOperations;
+
+    @Autowired
+    public StudentRepositoryImpl(RedisTemplate redisTemplate) {
+        this.redisTemplate = redisTemplate;
+    }
+
+    @PostConstruct
+    private void init() {
+        hashOperations = redisTemplate.opsForHash();
+    }
+
+    public void saveStudent(final Student student) {
+        hashOperations.put(KEY, student.getId(), student);
+    }
+
+    public void updateStudent(final Student student) {
+        hashOperations.put(KEY, student.getId(), student);
+    }
+
+    public Student findStudent(final String id) {
+        return (Student) hashOperations.get(KEY, id);
+    }
+
+    public Map findAllStudents() {
+        return hashOperations.entries(KEY);
+    }
+
+    public void deleteStudent(final String id) {
+        hashOperations.delete(KEY, id);
+    }
+}
diff --git a/spring-data-redis/src/main/resources/logback.xml b/spring-data-redis/src/main/resources/logback.xml
new file mode 100644
index 0000000000..215eeede64
--- /dev/null
+++ b/spring-data-redis/src/main/resources/logback.xml
@@ -0,0 +1,20 @@
+
+
+    
+        
+            web - %date [%thread] %-5level %logger{36} - %message%n
+            
+        
+    
+
+    
+    
+
+    
+    
+
+    
+        
+    
+
+
\ No newline at end of file
diff --git a/spring-data-redis/src/main/resources/test.png b/spring-data-redis/src/main/resources/test.png
new file mode 100644
index 0000000000..c3b5e80276
Binary files /dev/null and b/spring-data-redis/src/main/resources/test.png differ
diff --git a/spring-data-redis/src/test/java/org/baeldung/spring/data/redis/repo/StudentRepositoryTest.java b/spring-data-redis/src/test/java/org/baeldung/spring/data/redis/repo/StudentRepositoryTest.java
new file mode 100644
index 0000000000..08540abd36
--- /dev/null
+++ b/spring-data-redis/src/test/java/org/baeldung/spring/data/redis/repo/StudentRepositoryTest.java
@@ -0,0 +1,60 @@
+package org.baeldung.spring.data.redis.repo;
+
+import org.baeldung.spring.data.redis.config.RedisConfig;
+import org.baeldung.spring.data.redis.model.Student;
+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 java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = RedisConfig.class)
+public class StudentRepositoryTest {
+
+    @Autowired
+    private StudentRepository studentRepository;
+
+    @Test
+    public void whenSavingStudent_thenAvailableOnRetrieval() throws Exception {
+        final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1);
+        studentRepository.saveStudent(student);
+        final Student retrievedStudent = studentRepository.findStudent(student.getId());
+        assertEquals(student.getId(), retrievedStudent.getId());
+    }
+
+    @Test
+    public void whenUpdatingStudent_thenAvailableOnRetrieval() throws Exception {
+        final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1);
+        studentRepository.saveStudent(student);
+        student.setName("Richard Watson");
+        studentRepository.saveStudent(student);
+        final Student retrievedStudent = studentRepository.findStudent(student.getId());
+        assertEquals(student.getName(), retrievedStudent.getName());
+    }
+
+    @Test
+    public void whenSavingStudents_thenAllShouldAvailableOnRetrieval() throws Exception {
+        final Student engStudent = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1);
+        final Student medStudent = new Student("Med2015001", "Gareth Houston", Student.Gender.MALE, 2);
+        studentRepository.saveStudent(engStudent);
+        studentRepository.saveStudent(medStudent);
+        final Map retrievedStudent = studentRepository.findAllStudents();
+        assertEquals(retrievedStudent.size(), 2);
+    }
+
+    @Test
+    public void whenDeletingStudent_thenNotAvailableOnRetrieval() throws Exception {
+        final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1);
+        studentRepository.saveStudent(student);
+        studentRepository.deleteStudent(student.getId());
+        final Student retrievedStudent = studentRepository.findStudent(student.getId());
+        assertNull(retrievedStudent);
+    }
+}
\ No newline at end of file
diff --git a/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/ChildDao.java b/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/ChildDao.java
index 771da435c6..e068573c5c 100644
--- a/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/ChildDao.java
+++ b/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/ChildDao.java
@@ -8,7 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public class ChildDao extends AbstractHibernateDaoimplements IChildDao {
+public class ChildDao extends AbstractHibernateDao implements IChildDao {
 
     @Autowired
     private SessionFactory sessionFactory;
diff --git a/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/FooDao.java b/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/FooDao.java
index a5d995cec0..baf29c9ecd 100644
--- a/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/FooDao.java
+++ b/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/FooDao.java
@@ -8,7 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public class FooDao extends AbstractHibernateDaoimplements IFooDao {
+public class FooDao extends AbstractHibernateDao implements IFooDao {
 
     @Autowired
     private SessionFactory sessionFactory;
diff --git a/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/ParentDao.java b/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/ParentDao.java
index 207e01de58..5634137b63 100644
--- a/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/ParentDao.java
+++ b/spring-exceptions/src/main/java/org/baeldung/persistence/dao/impl/ParentDao.java
@@ -8,7 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public class ParentDao extends AbstractHibernateDaoimplements IParentDao {
+public class ParentDao extends AbstractHibernateDao implements IParentDao {
 
     @Autowired
     private SessionFactory sessionFactory;
diff --git a/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/ChildService.java b/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/ChildService.java
index 987466643b..89597313ea 100644
--- a/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/ChildService.java
+++ b/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/ChildService.java
@@ -9,7 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 @Service
-public class ChildService extends AbstractServiceimplements IChildService {
+public class ChildService extends AbstractService implements IChildService {
 
     @Autowired
     private IChildDao dao;
diff --git a/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/FooService.java b/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/FooService.java
index 382368bbd4..f0a4d7a649 100644
--- a/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/FooService.java
+++ b/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/FooService.java
@@ -9,7 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 @Service
-public class FooService extends AbstractServiceimplements IFooService {
+public class FooService extends AbstractService implements IFooService {
 
     @Autowired
     private IFooDao dao;
diff --git a/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/ParentService.java b/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/ParentService.java
index e40ccfd2f8..97c44f4a2f 100644
--- a/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/ParentService.java
+++ b/spring-exceptions/src/main/java/org/baeldung/persistence/service/impl/ParentService.java
@@ -9,7 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 @Service
-public class ParentService extends AbstractServiceimplements IParentService {
+public class ParentService extends AbstractService implements IParentService {
 
     @Autowired
     private IParentDao dao;
diff --git a/spring-freemarker/.gitignore b/spring-freemarker/.gitignore
new file mode 100644
index 0000000000..b83d22266a
--- /dev/null
+++ b/spring-freemarker/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/spring-freemarker/pom.xml b/spring-freemarker/pom.xml
new file mode 100644
index 0000000000..9bbdbcecfb
--- /dev/null
+++ b/spring-freemarker/pom.xml
@@ -0,0 +1,86 @@
+
+	4.0.0
+	com.freemarker.example
+	spring4-freemarker-example
+	war
+	1.0-SNAPSHOT
+	Spring Freemarker Example
+
+	
+		1.8
+		4.2.4.RELEASE
+		2.3.23
+		1.1.3
+		1.7.12
+		3.1.0
+		false
+	
+
+	
+
+		
+			org.springframework
+			spring-webmvc
+			${spring.version}
+			
+				
+					commons-logging
+					commons-logging
+				
+			
+		
+		
+		
+    		org.springframework
+    		spring-context-support
+    		${spring.version}
+		
+
+		
+		
+			org.slf4j
+			jcl-over-slf4j
+			${jcl.slf4j.version}
+		
+
+		
+			ch.qos.logback
+			logback-classic
+			${logback.version}
+		
+
+		
+		
+		
+			javax.servlet
+			javax.servlet-api
+			${servletapi.version}
+			provided
+		
+		
+		
+		
+			org.freemarker
+			freemarker
+			${freemarker.version}
+		
+
+	
+
+	
+		
+			
+				org.apache.maven.plugins
+				maven-compiler-plugin
+				3.3
+				
+					${jdk.version}
+					${jdk.version}
+					true
+				
+			
+		
+	
+
+
\ No newline at end of file
diff --git a/spring-freemarker/src/main/java/com/baeldung/freemarker/config/SpringWebConfig.java b/spring-freemarker/src/main/java/com/baeldung/freemarker/config/SpringWebConfig.java
new file mode 100644
index 0000000000..77f0712aca
--- /dev/null
+++ b/spring-freemarker/src/main/java/com/baeldung/freemarker/config/SpringWebConfig.java
@@ -0,0 +1,38 @@
+package com.baeldung.freemarker.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
+import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
+
+@EnableWebMvc
+@Configuration
+@ComponentScan({"com.baeldung.freemarker"})
+public class SpringWebConfig extends WebMvcConfigurerAdapter {
+
+	@Override
+	public void addResourceHandlers(ResourceHandlerRegistry registry) {
+		registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
+	}
+
+	@Bean 
+	public FreeMarkerViewResolver freemarkerViewResolver() { 
+		FreeMarkerViewResolver resolver = new FreeMarkerViewResolver(); 
+		resolver.setCache(true); 
+		resolver.setPrefix(""); 
+		resolver.setSuffix(".ftl"); 
+		return resolver; 
+	}
+
+	@Bean 
+	public FreeMarkerConfigurer freemarkerConfig() { 
+		FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer(); 
+		freeMarkerConfigurer.setTemplateLoaderPath("/WEB-INF/views/ftl/");
+		return freeMarkerConfigurer; 
+	}
+
+}
\ No newline at end of file
diff --git a/spring-freemarker/src/main/java/com/baeldung/freemarker/config/WebConfiguration.java b/spring-freemarker/src/main/java/com/baeldung/freemarker/config/WebConfiguration.java
new file mode 100644
index 0000000000..3d5ab964e7
--- /dev/null
+++ b/spring-freemarker/src/main/java/com/baeldung/freemarker/config/WebConfiguration.java
@@ -0,0 +1,22 @@
+package com.baeldung.freemarker.config;
+
+import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
+
+public class WebConfiguration extends AbstractAnnotationConfigDispatcherServletInitializer {
+
+	@Override
+	protected Class[] getServletConfigClasses() {
+		return new Class[] { SpringWebConfig.class };
+	}
+
+	@Override
+	protected String[] getServletMappings() {
+		return new String[] { "/" };
+	}
+
+	@Override
+	protected Class[] getRootConfigClasses() {
+		return null;
+	}
+
+}
\ No newline at end of file
diff --git a/spring-freemarker/src/main/java/com/baeldung/freemarker/controller/SpringController.java b/spring-freemarker/src/main/java/com/baeldung/freemarker/controller/SpringController.java
new file mode 100644
index 0000000000..b911a4975b
--- /dev/null
+++ b/spring-freemarker/src/main/java/com/baeldung/freemarker/controller/SpringController.java
@@ -0,0 +1,48 @@
+package com.baeldung.freemarker.controller;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import com.baeldung.freemarker.model.Car;
+
+@Controller
+public class SpringController {
+
+	private static List carList = new ArrayList();
+	
+	@RequestMapping(value = "/", method = RequestMethod.GET)
+	public String home(Locale locale, Model model) {
+		return "redirect:/cars";
+	}
+	
+	static {
+		carList.add(new Car("Honda", "Civic"));
+		carList.add(new Car("Toyota", "Camry"));
+		carList.add(new Car("Nissan", "Altima"));
+	}
+
+
+	@RequestMapping(value = "/cars", method = RequestMethod.GET)
+	public String init(@ModelAttribute("model") ModelMap model) {
+		model.addAttribute("carList", carList);
+		return "index";
+	}
+
+	@RequestMapping(value = "/add", method = RequestMethod.POST)
+	public String addCar(@ModelAttribute("car") Car car) {
+		if (null != car && null != car.getMake() && null != car.getModel() 
+				&& !car.getMake().isEmpty() && !car.getModel().isEmpty()) {
+			carList.add(car);
+		}
+		return "redirect:/cars";
+	}
+	
+}
diff --git a/spring-freemarker/src/main/java/com/baeldung/freemarker/model/Car.java b/spring-freemarker/src/main/java/com/baeldung/freemarker/model/Car.java
new file mode 100644
index 0000000000..e400d87608
--- /dev/null
+++ b/spring-freemarker/src/main/java/com/baeldung/freemarker/model/Car.java
@@ -0,0 +1,33 @@
+package com.baeldung.freemarker.model;
+
+public class Car {
+
+	private String make;
+	private String model;
+	
+	public Car(){
+		
+	}
+	
+	public Car(String make, String model) {
+        this.make  = make;
+        this.model = model;
+    }
+
+	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;
+	}
+
+}
diff --git a/spring-freemarker/src/main/resources/log4j.xml b/spring-freemarker/src/main/resources/log4j.xml
new file mode 100644
index 0000000000..ae7d4b5ca4
--- /dev/null
+++ b/spring-freemarker/src/main/resources/log4j.xml
@@ -0,0 +1,41 @@
+
+
+
+
+	
+	
+		
+		
+			
+		
+	
+	
+	
+	
+		
+	
+	
+	
+	
+		
+	
+	
+	
+		
+	
+	
+	
+		
+	
+
+	
+		
+	
+
+	
+	
+		
+		
+	
+	
+
diff --git a/spring-freemarker/src/main/webapp/WEB-INF/views/ftl/index.ftl b/spring-freemarker/src/main/webapp/WEB-INF/views/ftl/index.ftl
new file mode 100644
index 0000000000..899c9b9271
--- /dev/null
+++ b/spring-freemarker/src/main/webapp/WEB-INF/views/ftl/index.ftl
@@ -0,0 +1,61 @@
+
+ FreeMarker Spring MVC Hello World
+
+
+
+
+
+
+
+ +
+ Add Car +
+ Make :
+ Model:
+ +
+
+ +
+ + + + + <#list model["carList"] as car> + + + + +
Make Model
${car.make} ${car.model}
+ +
+ + \ No newline at end of file diff --git a/spring-freemarker/src/test/resources/log4j.xml b/spring-freemarker/src/test/resources/log4j.xml new file mode 100644 index 0000000000..9b1538d31a --- /dev/null +++ b/spring-freemarker/src/test/resources/log4j.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-hibernate3/src/main/java/org/baeldung/persistence/dao/FooDao.java b/spring-hibernate3/src/main/java/org/baeldung/persistence/dao/FooDao.java index cb8d7488ea..23de04169e 100644 --- a/spring-hibernate3/src/main/java/org/baeldung/persistence/dao/FooDao.java +++ b/spring-hibernate3/src/main/java/org/baeldung/persistence/dao/FooDao.java @@ -4,7 +4,7 @@ import org.baeldung.persistence.model.Foo; import org.springframework.stereotype.Repository; @Repository -public class FooDao extends AbstractHibernateDaoimplements IFooDao { +public class FooDao extends AbstractHibernateDao implements IFooDao { public FooDao() { super(); diff --git a/spring-hibernate4/pom.xml b/spring-hibernate4/pom.xml index 8fabb56ab7..652636b7cc 100644 --- a/spring-hibernate4/pom.xml +++ b/spring-hibernate4/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - org.baeldung + com.baeldung spring-hibernate4 0.1-SNAPSHOT @@ -15,6 +15,16 @@ spring-context ${org.springframework.version} + + org.springframework + spring-aspects + ${org.springframework.version} + + + org.springframework.security + spring-security-core + ${org.springframework.security.version} + @@ -23,21 +33,35 @@ spring-orm ${org.springframework.version} + + org.springframework.data + spring-data-jpa + ${org.springframework.data.version} + org.hibernate hibernate-core ${hibernate.version} - org.javassist - javassist - ${javassist.version} + org.hibernate + hibernate-envers + ${hibernate-envers.version} + + + javax.transaction + jta + ${jta.version} + + + javax.el + javax.el-api + ${el-api.version} mysql mysql-connector-java ${mysql-connector-java.version} - runtime @@ -82,7 +106,7 @@ ${org.springframework.version} test - + junit junit @@ -90,12 +114,27 @@ test + + org.springframework.security + spring-security-test + ${org.springframework.security.version} + test + + org.hamcrest hamcrest-core ${org.hamcrest.version} test + + + junit + junit-dep + ${junit.version} + test + + org.hamcrest hamcrest-library @@ -175,18 +214,22 @@ 4.2.4.RELEASE - 4.0.3.RELEASE - 3.20.0-GA - + 4.0.3.RELEASE + 1.9.2.RELEASE + 3.20.0-GA + 4.3.11.Final + ${hibernate.version} 5.1.37 - 7.0.42 + 8.0.30 + 1.1 + 2.2.4 1.7.13 1.1.3 - + 5.2.2.Final @@ -196,7 +239,7 @@ 1.3 - 4.12 + 4.11 1.10.19 4.4.1 @@ -209,7 +252,8 @@ 2.18.1 2.7 1.4.15 + - \ No newline at end of file + diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java new file mode 100644 index 0000000000..182b493592 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.model.Bar; + +public interface IBarAuditableDao extends IBarDao, IAuditOperations { + // +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java new file mode 100644 index 0000000000..4d7db64240 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.persistence.dao; + +import java.io.Serializable; + +import com.baeldung.persistence.model.Bar; +import org.springframework.data.repository.CrudRepository; + +public interface IBarCrudRepository extends CrudRepository { + // +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarDao.java new file mode 100644 index 0000000000..7896a2a84a --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Bar; + +public interface IBarDao extends IOperations { + // +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IChildDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IChildDao.java new file mode 100644 index 0000000000..a55a0b0598 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IChildDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.model.Child; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IChildDao extends IOperations { + // +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java new file mode 100644 index 0000000000..ddbb685988 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.model.Foo; + +public interface IFooAuditableDao extends IFooDao, IAuditOperations { + // +} \ No newline at end of file diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IFooDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IFooDao.java new file mode 100644 index 0000000000..0935772dbd --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IFooDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IFooDao extends IOperations { + // +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IParentDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IParentDao.java new file mode 100644 index 0000000000..03680158bb --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IParentDao.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.dao; + +import com.baeldung.persistence.model.Parent; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IParentDao extends IOperations { + // +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java new file mode 100644 index 0000000000..5a6c76a93a --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java @@ -0,0 +1,14 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; + +import com.google.common.base.Preconditions; + +public abstract class AbstractDao implements IOperations { + + protected Class clazz; + + protected final void setClazz(final Class clazzToSet) { + clazz = Preconditions.checkNotNull(clazzToSet); + } +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java new file mode 100644 index 0000000000..41184669ad --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java @@ -0,0 +1,37 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +import org.hibernate.envers.AuditReader; +import org.hibernate.envers.AuditReaderFactory; +import org.hibernate.envers.query.AuditQuery; + +@SuppressWarnings("unchecked") +public class AbstractHibernateAuditableDao extends AbstractHibernateDao implements IAuditOperations { + + @Override + public List getEntitiesAtRevision(final Number revision) { + final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession()); + final AuditQuery query = auditReader.createQuery().forEntitiesAtRevision(clazz, revision); + final List resultList = query.getResultList(); + return resultList; + } + + @Override + public List getEntitiesModifiedAtRevision(final Number revision) { + final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession()); + final AuditQuery query = auditReader.createQuery().forEntitiesModifiedAtRevision(clazz, revision); + final List resultList = query.getResultList(); + return resultList; + } + + @Override + public List getRevisions() { + final AuditReader auditReader = AuditReaderFactory.get(getCurrentSession()); + final AuditQuery query = auditReader.createQuery().forRevisionsOfEntity(clazz, true, true); + final List resultList = query.getResultList(); + return resultList; + } + +} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractHibernateDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java similarity index 62% rename from spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractHibernateDao.java rename to spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java index 65e57afcb3..f3ade67f80 100644 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/AbstractHibernateDao.java +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java @@ -1,4 +1,4 @@ -package org.baeldung.persistence.dao.common; +package com.baeldung.persistence.dao.common; import java.io.Serializable; import java.util.List; @@ -10,55 +10,49 @@ import org.springframework.beans.factory.annotation.Autowired; import com.google.common.base.Preconditions; @SuppressWarnings("unchecked") -public abstract class AbstractHibernateDao implements IOperations { - private Class clazz; +public abstract class AbstractHibernateDao extends AbstractDao implements IOperations { @Autowired - private SessionFactory sessionFactory; + protected SessionFactory sessionFactory; // API - protected final void setClazz(final Class clazzToSet) { - clazz = Preconditions.checkNotNull(clazzToSet); - } - @Override - public final T findOne(final long id) { + public T findOne(final long id) { return (T) getCurrentSession().get(clazz, id); } @Override - public final List findAll() { + public List findAll() { return getCurrentSession().createQuery("from " + clazz.getName()).list(); } @Override - public final void create(final T entity) { + public void create(final T entity) { Preconditions.checkNotNull(entity); - // getCurrentSession().persist(entity); getCurrentSession().saveOrUpdate(entity); } @Override - public final T update(final T entity) { + public T update(final T entity) { Preconditions.checkNotNull(entity); return (T) getCurrentSession().merge(entity); } @Override - public final void delete(final T entity) { + public void delete(final T entity) { Preconditions.checkNotNull(entity); getCurrentSession().delete(entity); } @Override - public final void deleteById(final long entityId) { + public void deleteById(final long entityId) { final T entity = findOne(entityId); Preconditions.checkState(entity != null); delete(entity); } - protected final Session getCurrentSession() { + protected Session getCurrentSession() { return sessionFactory.getCurrentSession(); } diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java new file mode 100644 index 0000000000..69f8e58c25 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java @@ -0,0 +1,56 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; + +public class AbstractJpaDao extends AbstractDao implements IOperations { + + @PersistenceContext + private EntityManager em; + + // API + + @Override + public T findOne(final long id) { + return em.find(clazz, Long.valueOf(id).intValue()); + } + + @Override + public List findAll() { + final CriteriaBuilder cb = em.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createQuery(clazz); + final Root rootEntry = cq.from(clazz); + final CriteriaQuery all = cq.select(rootEntry); + final TypedQuery allQuery = em.createQuery(all); + return allQuery.getResultList(); + } + + @Override + public void create(final T entity) { + em.persist(entity); + } + + @Override + public T update(final T entity) { + em.merge(entity); + return entity; + } + + @Override + public void delete(final T entity) { + em.remove(entity); + } + + @Override + public void deleteById(final long entityId) { + delete(findOne(entityId)); + } + +} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/GenericHibernateDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java similarity index 76% rename from spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/GenericHibernateDao.java rename to spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java index 018e367209..18b16fa033 100644 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/GenericHibernateDao.java +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java @@ -1,4 +1,4 @@ -package org.baeldung.persistence.dao.common; +package com.baeldung.persistence.dao.common; import java.io.Serializable; @@ -8,6 +8,6 @@ import org.springframework.stereotype.Repository; @Repository @Scope(BeanDefinition.SCOPE_PROTOTYPE) -public class GenericHibernateDao extends AbstractHibernateDaoimplements IGenericDao { +public class GenericHibernateDao extends AbstractHibernateDao implements IGenericDao { // } \ No newline at end of file diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java new file mode 100644 index 0000000000..169d3fed72 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java @@ -0,0 +1,14 @@ +package com.baeldung.persistence.dao.common; + +import java.io.Serializable; +import java.util.List; + +public interface IAuditOperations { + + List getEntitiesAtRevision(Number revision); + + List getEntitiesModifiedAtRevision(Number revision); + + List getRevisions(); + +} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/IGenericDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java similarity index 72% rename from spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/IGenericDao.java rename to spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java index b7876deea4..8d8af18394 100644 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/IGenericDao.java +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java @@ -1,4 +1,4 @@ -package org.baeldung.persistence.dao.common; +package com.baeldung.persistence.dao.common; import java.io.Serializable; diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/IOperations.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IOperations.java similarity index 87% rename from spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/IOperations.java rename to spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IOperations.java index 1c84b06c85..4ef99221ab 100644 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/common/IOperations.java +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IOperations.java @@ -1,4 +1,4 @@ -package org.baeldung.persistence.dao.common; +package com.baeldung.persistence.dao.common; import java.io.Serializable; import java.util.List; diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java new file mode 100644 index 0000000000..e12b6ae2da --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java @@ -0,0 +1,28 @@ +package com.baeldung.persistence.dao.impl; + +import java.util.List; + +import com.baeldung.persistence.dao.IBarAuditableDao; +import com.baeldung.persistence.dao.common.AbstractHibernateAuditableDao; +import com.baeldung.persistence.model.Bar; + +public class BarAuditableDao extends AbstractHibernateAuditableDao implements IBarAuditableDao { + + public BarAuditableDao() { + super(); + + setClazz(Bar.class); + } + + // API + + @Override + public List getRevisions() { + final List resultList = super.getRevisions(); + for (final Bar bar : resultList) { + bar.getFooSet().size(); // force FooSet initialization + } + return resultList; + } + +} \ No newline at end of file diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java new file mode 100644 index 0000000000..0ead802dc5 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java @@ -0,0 +1,19 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.common.AbstractHibernateDao; +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.model.Bar; +import org.springframework.stereotype.Repository; + +@Repository +public class BarDao extends AbstractHibernateDao implements IBarDao { + + public BarDao() { + super(); + + setClazz(Bar.class); + } + + // API + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java new file mode 100644 index 0000000000..e0fa382d41 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java @@ -0,0 +1,19 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.dao.common.AbstractJpaDao; +import com.baeldung.persistence.model.Bar; +import org.springframework.stereotype.Repository; + +@Repository +public class BarJpaDao extends AbstractJpaDao implements IBarDao { + + public BarJpaDao() { + super(); + + setClazz(Bar.class); + } + + // API + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java new file mode 100644 index 0000000000..b55da6e43a --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java @@ -0,0 +1,19 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.common.AbstractHibernateDao; +import com.baeldung.persistence.model.Child; +import com.baeldung.persistence.dao.IChildDao; +import org.springframework.stereotype.Repository; + +@Repository +public class ChildDao extends AbstractHibernateDao implements IChildDao { + + public ChildDao() { + super(); + + setClazz(Child.class); + } + + // API + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java new file mode 100644 index 0000000000..05064c1478 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java @@ -0,0 +1,17 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.common.AbstractHibernateAuditableDao; +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.dao.IFooAuditableDao; + +public class FooAuditableDao extends AbstractHibernateAuditableDao implements IFooAuditableDao { + + public FooAuditableDao() { + super(); + + setClazz(Foo.class); + } + + // API + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java new file mode 100644 index 0000000000..787c449b1d --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java @@ -0,0 +1,19 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.common.AbstractHibernateDao; +import com.baeldung.persistence.dao.IFooDao; +import com.baeldung.persistence.model.Foo; +import org.springframework.stereotype.Repository; + +@Repository +public class FooDao extends AbstractHibernateDao implements IFooDao { + + public FooDao() { + super(); + + setClazz(Foo.class); + } + + // API + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java new file mode 100644 index 0000000000..4602b5f30e --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java @@ -0,0 +1,19 @@ +package com.baeldung.persistence.dao.impl; + +import com.baeldung.persistence.dao.IParentDao; +import com.baeldung.persistence.dao.common.AbstractHibernateDao; +import com.baeldung.persistence.model.Parent; +import org.springframework.stereotype.Repository; + +@Repository +public class ParentDao extends AbstractHibernateDao implements IParentDao { + + public ParentDao() { + super(); + + setClazz(Parent.class); + } + + // API + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Bar.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Bar.java new file mode 100644 index 0000000000..efc6367116 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Bar.java @@ -0,0 +1,242 @@ +package com.baeldung.persistence.model; + +import java.io.Serializable; +import java.util.Date; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; +import javax.persistence.PrePersist; +import javax.persistence.PreRemove; +import javax.persistence.PreUpdate; + +import org.hibernate.annotations.OrderBy; +import org.hibernate.envers.Audited; +import org.jboss.logging.Logger; +import org.springframework.data.annotation.CreatedBy; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedBy; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import com.google.common.collect.Sets; + +@Entity +@NamedQuery(name = "Bar.findAll", query = "SELECT b FROM Bar b") +@Audited +@EntityListeners(AuditingEntityListener.class) +public class Bar implements Serializable { + + private static Logger logger = Logger.getLogger(Bar.class); + + public enum OPERATION { + INSERT, UPDATE, DELETE; + private String value; + + OPERATION() { + value = toString(); + } + + public String getValue() { + return value; + } + + public static OPERATION parse(final String value) { + OPERATION operation = null; + for (final OPERATION op : OPERATION.values()) { + if (op.getValue().equals(value)) { + operation = op; + break; + } + } + return operation; + } + }; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "id") + private int id; + + @Column(name = "name") + private String name; + + @OneToMany(mappedBy = "bar", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @OrderBy(clause = "NAME DESC") + // @NotAudited + private Set fooSet = Sets.newHashSet(); + + @Column(name = "operation") + private String operation; + + @Column(name = "timestamp") + private long timestamp; + + @Column(name = "created_date") + @CreatedDate + private long createdDate; + + @Column(name = "modified_date") + @LastModifiedDate + private long modifiedDate; + + @Column(name = "created_by") + @CreatedBy + private String createdBy; + + @Column(name = "modified_by") + @LastModifiedBy + private String modifiedBy; + + public Bar() { + super(); + } + + public Bar(final String name) { + super(); + + this.name = name; + } + + // API + + public Set getFooSet() { + return fooSet; + } + + public void setFooSet(final Set fooSet) { + this.fooSet = fooSet; + } + + public int 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; + } + + public OPERATION getOperation() { + return OPERATION.parse(operation); + } + + public void setOperation(final OPERATION operation) { + this.operation = operation.getValue(); + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(final long timestamp) { + this.timestamp = timestamp; + } + + public long getCreatedDate() { + return createdDate; + } + + public void setCreatedDate(final long createdDate) { + this.createdDate = createdDate; + } + + public long getModifiedDate() { + return modifiedDate; + } + + public void setModifiedDate(final long modifiedDate) { + this.modifiedDate = modifiedDate; + } + + public String getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(final String createdBy) { + this.createdBy = createdBy; + } + + public String getModifiedBy() { + return modifiedBy; + } + + public void setModifiedBy(final String modifiedBy) { + this.modifiedBy = modifiedBy; + } + + public void setOperation(final String operation) { + this.operation = operation; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Bar other = (Bar) obj; + 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("Bar [name=").append(name).append("]"); + return builder.toString(); + } + + @PrePersist + public void onPrePersist() { + logger.info("@PrePersist"); + audit(OPERATION.INSERT); + } + + @PreUpdate + public void onPreUpdate() { + logger.info("@PreUpdate"); + audit(OPERATION.UPDATE); + } + + @PreRemove + public void onPreRemove() { + logger.info("@PreRemove"); + audit(OPERATION.DELETE); + } + + private void audit(final OPERATION operation) { + setOperation(operation); + setTimestamp((new Date()).getTime()); + } + +} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Child.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Child.java similarity index 95% rename from spring-hibernate4/src/main/java/org/baeldung/persistence/model/Child.java rename to spring-hibernate4/src/main/java/com/baeldung/persistence/model/Child.java index 4eec4cf1d3..19cfb2e237 100644 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Child.java +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Child.java @@ -1,4 +1,4 @@ -package org.baeldung.persistence.model; +package com.baeldung.persistence.model; import java.io.Serializable; diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Foo.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java similarity index 95% rename from spring-hibernate4/src/main/java/org/baeldung/persistence/model/Foo.java rename to spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java index 974535e058..6b48c1fa66 100644 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Foo.java +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java @@ -1,4 +1,4 @@ -package org.baeldung.persistence.model; +package com.baeldung.persistence.model; import java.io.Serializable; @@ -12,7 +12,11 @@ import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; +import org.hibernate.envers.Audited; + @Entity +@Audited +// @Proxy(lazy = false) public class Foo implements Serializable { @Id diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Parent.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Parent.java similarity index 96% rename from spring-hibernate4/src/main/java/org/baeldung/persistence/model/Parent.java rename to spring-hibernate4/src/main/java/com/baeldung/persistence/model/Parent.java index 19e405615d..fa6948990b 100644 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Parent.java +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Parent.java @@ -1,4 +1,4 @@ -package org.baeldung.persistence.model; +package com.baeldung.persistence.model; import java.io.Serializable; diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java new file mode 100644 index 0000000000..33e5634d12 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.model.Bar; + +public interface IBarAuditableService extends IBarService, IAuditOperations { + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IBarService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IBarService.java new file mode 100644 index 0000000000..21185b5990 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IBarService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Bar; + +public interface IBarService extends IOperations { + // +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IChildService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IChildService.java new file mode 100644 index 0000000000..afe67a70c2 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IChildService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.model.Child; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IChildService extends IOperations { + // +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java new file mode 100644 index 0000000000..b787e7fe91 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.model.Foo; + +public interface IFooAuditableService extends IFooService, IAuditOperations { + // +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IFooService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IFooService.java new file mode 100644 index 0000000000..ffdb53964a --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IFooService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IFooService extends IOperations { + // +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IParentService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IParentService.java new file mode 100644 index 0000000000..f941416aac --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IParentService.java @@ -0,0 +1,8 @@ +package com.baeldung.persistence.service; + +import com.baeldung.persistence.model.Parent; +import com.baeldung.persistence.dao.common.IOperations; + +public interface IParentService extends IOperations { + // +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java new file mode 100644 index 0000000000..2695d7760a --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java @@ -0,0 +1,30 @@ +package com.baeldung.persistence.service.common; + +import java.io.Serializable; +import java.util.List; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.dao.common.IOperations; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(value = "hibernateTransactionManager") +public abstract class AbstractHibernateAuditableService extends AbstractHibernateService implements IOperations, IAuditOperations { + + @Override + public List getEntitiesAtRevision(final Number revision) { + return getAuditableDao().getEntitiesAtRevision(revision); + } + + @Override + public List getEntitiesModifiedAtRevision(final Number revision) { + return getAuditableDao().getEntitiesModifiedAtRevision(revision); + } + + @Override + public List getRevisions() { + return getAuditableDao().getRevisions(); + } + + abstract protected IAuditOperations getAuditableDao(); + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java new file mode 100644 index 0000000000..02b8ccf48b --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java @@ -0,0 +1,42 @@ +package com.baeldung.persistence.service.common; + +import java.io.Serializable; +import java.util.List; + +import com.baeldung.persistence.dao.common.IOperations; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(value = "hibernateTransactionManager") +public abstract class AbstractHibernateService extends AbstractService implements IOperations { + + @Override + public T findOne(final long id) { + return super.findOne(id); + } + + @Override + public List findAll() { + return super.findAll(); + } + + @Override + public void create(final T entity) { + super.create(entity); + } + + @Override + public T update(final T entity) { + return super.update(entity); + } + + @Override + public void delete(final T entity) { + super.delete(entity); + } + + @Override + public void deleteById(final long entityId) { + super.deleteById(entityId); + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java new file mode 100644 index 0000000000..a1c6fe9edf --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java @@ -0,0 +1,42 @@ +package com.baeldung.persistence.service.common; + +import java.io.Serializable; +import java.util.List; + +import com.baeldung.persistence.dao.common.IOperations; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(value = "jpaTransactionManager") +public abstract class AbstractJpaService extends AbstractService implements IOperations { + + @Override + public T findOne(final long id) { + return super.findOne(id); + } + + @Override + public List findAll() { + return super.findAll(); + } + + @Override + public void create(final T entity) { + super.create(entity); + } + + @Override + public T update(final T entity) { + return super.update(entity); + } + + @Override + public void delete(final T entity) { + super.delete(entity); + } + + @Override + public void deleteById(final long entityId) { + super.deleteById(entityId); + } + +} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractService.java similarity index 80% rename from spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractService.java rename to spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractService.java index 3b32bc3ebb..9b001b1fac 100644 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/common/AbstractService.java +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractService.java @@ -1,12 +1,10 @@ -package org.baeldung.persistence.service.common; +package com.baeldung.persistence.service.common; import java.io.Serializable; import java.util.List; -import org.baeldung.persistence.dao.common.IOperations; -import org.springframework.transaction.annotation.Transactional; +import com.baeldung.persistence.dao.common.IOperations; -@Transactional public abstract class AbstractService implements IOperations { @Override diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java new file mode 100644 index 0000000000..cef483e6bf --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java @@ -0,0 +1,46 @@ +package com.baeldung.persistence.service.common; + +import java.io.Serializable; +import java.util.List; + +import com.baeldung.persistence.dao.common.IOperations; +import org.springframework.data.repository.CrudRepository; +import org.springframework.transaction.annotation.Transactional; + +import com.google.common.collect.Lists; + +@Transactional(value = "jpaTransactionManager") +public abstract class AbstractSpringDataJpaService implements IOperations { + + @Override + public T findOne(final long id) { + return getDao().findOne(Long.valueOf(id)); + } + + @Override + public List findAll() { + return Lists.newArrayList(getDao().findAll()); + } + + @Override + public void create(final T entity) { + getDao().save(entity); + } + + @Override + public T update(final T entity) { + return getDao().save(entity); + } + + @Override + public void delete(final T entity) { + getDao().delete(entity); + } + + @Override + public void deleteById(final long entityId) { + getDao().delete(Long.valueOf(entityId)); + } + + protected abstract CrudRepository getDao(); +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java new file mode 100644 index 0000000000..d84c28caa5 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java @@ -0,0 +1,41 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.service.common.AbstractHibernateAuditableService; +import com.baeldung.persistence.dao.IBarAuditableDao; +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.service.IBarAuditableService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class BarAuditableService extends AbstractHibernateAuditableService implements IBarAuditableService { + + @Autowired + @Qualifier("barHibernateDao") + private IBarDao dao; + + @Autowired + @Qualifier("barHibernateAuditableDao") + private IBarAuditableDao auditDao; + + public BarAuditableService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + + @Override + protected IAuditOperations getAuditableDao() { + return auditDao; + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java new file mode 100644 index 0000000000..1c1b7a2274 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java @@ -0,0 +1,30 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.service.IBarService; +import com.baeldung.persistence.service.common.AbstractJpaService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class BarJpaService extends AbstractJpaService implements IBarService { + + @Autowired + @Qualifier("barJpaDao") + private IBarDao dao; + + public BarJpaService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + +} \ No newline at end of file diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarService.java new file mode 100644 index 0000000000..32d1f919c5 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarService.java @@ -0,0 +1,30 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.service.IBarService; +import com.baeldung.persistence.service.common.AbstractHibernateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class BarService extends AbstractHibernateService implements IBarService { + + @Autowired + @Qualifier("barHibernateDao") + private IBarDao dao; + + public BarService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java new file mode 100644 index 0000000000..4a55d08a35 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java @@ -0,0 +1,26 @@ +package com.baeldung.persistence.service.impl; + +import java.io.Serializable; + +import com.baeldung.persistence.service.common.AbstractSpringDataJpaService; +import com.baeldung.persistence.dao.IBarCrudRepository; +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.service.IBarService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.repository.CrudRepository; + +public class BarSpringDataJpaService extends AbstractSpringDataJpaService implements IBarService { + + @Autowired + private IBarCrudRepository dao; + + public BarSpringDataJpaService() { + super(); + } + + @Override + protected CrudRepository getDao() { + return dao; + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/ChildService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/ChildService.java new file mode 100644 index 0000000000..417fe2c49a --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/ChildService.java @@ -0,0 +1,28 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.model.Child; +import com.baeldung.persistence.service.IChildService; +import com.baeldung.persistence.dao.IChildDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.service.common.AbstractHibernateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ChildService extends AbstractHibernateService implements IChildService { + + @Autowired + private IChildDao dao; + + public ChildService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java new file mode 100644 index 0000000000..45ad315c42 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java @@ -0,0 +1,41 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.dao.common.IAuditOperations; +import com.baeldung.persistence.service.IFooAuditableService; +import com.baeldung.persistence.service.common.AbstractHibernateAuditableService; +import com.baeldung.persistence.dao.IFooAuditableDao; +import com.baeldung.persistence.dao.IFooDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Foo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class FooAuditableService extends AbstractHibernateAuditableService implements IFooAuditableService { + + @Autowired + @Qualifier("fooHibernateDao") + private IFooDao dao; + + @Autowired + @Qualifier("fooHibernateAuditableDao") + private IFooAuditableDao auditDao; + + public FooAuditableService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + + @Override + protected IAuditOperations getAuditableDao() { + return auditDao; + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/FooService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/FooService.java new file mode 100644 index 0000000000..84cf018fee --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/FooService.java @@ -0,0 +1,30 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.dao.IFooDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.service.IFooService; +import com.baeldung.persistence.service.common.AbstractHibernateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class FooService extends AbstractHibernateService implements IFooService { + + @Autowired + @Qualifier("fooHibernateDao") + private IFooDao dao; + + public FooService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/ParentService.java b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/ParentService.java new file mode 100644 index 0000000000..078acfc369 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/ParentService.java @@ -0,0 +1,28 @@ +package com.baeldung.persistence.service.impl; + +import com.baeldung.persistence.model.Parent; +import com.baeldung.persistence.service.IParentService; +import com.baeldung.persistence.dao.IParentDao; +import com.baeldung.persistence.dao.common.IOperations; +import com.baeldung.persistence.service.common.AbstractHibernateService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ParentService extends AbstractHibernateService implements IParentService { + + @Autowired + private IParentDao dao; + + public ParentService() { + super(); + } + + // API + + @Override + protected IOperations getDao() { + return dao; + } + +} diff --git a/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java b/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java new file mode 100644 index 0000000000..35e80b81a5 --- /dev/null +++ b/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java @@ -0,0 +1,179 @@ +package com.baeldung.spring; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.apache.tomcat.dbcp.dbcp2.BasicDataSource; +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.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.hibernate4.HibernateTransactionManager; +import org.springframework.orm.hibernate4.LocalSessionFactoryBean; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.JpaVendorAdapter; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import com.baeldung.persistence.dao.IBarAuditableDao; +import com.baeldung.persistence.dao.IBarDao; +import com.baeldung.persistence.dao.IFooAuditableDao; +import com.baeldung.persistence.dao.IFooDao; +import com.baeldung.persistence.dao.impl.BarAuditableDao; +import com.baeldung.persistence.dao.impl.BarDao; +import com.baeldung.persistence.dao.impl.BarJpaDao; +import com.baeldung.persistence.dao.impl.FooAuditableDao; +import com.baeldung.persistence.dao.impl.FooDao; +import com.baeldung.persistence.service.IBarAuditableService; +import com.baeldung.persistence.service.IBarService; +import com.baeldung.persistence.service.IFooAuditableService; +import com.baeldung.persistence.service.IFooService; +import com.baeldung.persistence.service.impl.BarAuditableService; +import com.baeldung.persistence.service.impl.BarJpaService; +import com.baeldung.persistence.service.impl.BarSpringDataJpaService; +import com.baeldung.persistence.service.impl.FooAuditableService; +import com.baeldung.persistence.service.impl.FooService; +import com.google.common.base.Preconditions; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager") +@EnableJpaAuditing +@PropertySource({ "classpath:persistence-mysql.properties" }) +@ComponentScan({ "com.baeldung.persistence" }) +public class PersistenceConfig { + + @Autowired + private Environment env; + + public PersistenceConfig() { + super(); + } + + @Bean + public LocalSessionFactoryBean sessionFactory() { + final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); + sessionFactory.setDataSource(restDataSource()); + sessionFactory.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + sessionFactory.setHibernateProperties(hibernateProperties()); + + return sessionFactory; + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); + emf.setDataSource(restDataSource()); + emf.setPackagesToScan(new String[] { "com.baeldung.persistence.model" }); + + final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + emf.setJpaVendorAdapter(vendorAdapter); + emf.setJpaProperties(hibernateProperties()); + + return emf; + } + + @Bean + public DataSource restDataSource() { + final BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); + dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); + dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); + dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); + + return dataSource; + } + + @Bean + public PlatformTransactionManager hibernateTransactionManager() { + final HibernateTransactionManager transactionManager = new HibernateTransactionManager(); + transactionManager.setSessionFactory(sessionFactory().getObject()); + return transactionManager; + } + + @Bean + public PlatformTransactionManager jpaTransactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + @Bean + public IBarService barJpaService() { + return new BarJpaService(); + } + + @Bean + public IBarService barSpringDataJpaService() { + return new BarSpringDataJpaService(); + } + + @Bean + public IFooService fooHibernateService() { + return new FooService(); + } + + @Bean + public IBarAuditableService barHibernateAuditableService() { + return new BarAuditableService(); + } + + @Bean + public IFooAuditableService fooHibernateAuditableService() { + return new FooAuditableService(); + } + + @Bean + public IBarDao barJpaDao() { + return new BarJpaDao(); + } + + @Bean + public IBarDao barHibernateDao() { + return new BarDao(); + } + + @Bean + public IBarAuditableDao barHibernateAuditableDao() { + return new BarAuditableDao(); + } + + @Bean + public IFooDao fooHibernateDao() { + return new FooDao(); + } + + @Bean + public IFooAuditableDao fooHibernateAuditableDao() { + return new FooAuditableDao(); + } + + private final Properties hibernateProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + + hibernateProperties.setProperty("hibernate.show_sql", "true"); + // hibernateProperties.setProperty("hibernate.format_sql", "true"); + // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); + + // Envers properties + hibernateProperties.setProperty("org.hibernate.envers.audit_table_suffix", env.getProperty("envers.audit_table_suffix")); + + return hibernateProperties; + } + +} \ No newline at end of file diff --git a/spring-hibernate4/src/main/java/org/baeldung/spring/PersistenceXmlConfig.java b/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java similarity index 83% rename from spring-hibernate4/src/main/java/org/baeldung/spring/PersistenceXmlConfig.java rename to spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java index f5857ec425..9cbeb8e1f8 100644 --- a/spring-hibernate4/src/main/java/org/baeldung/spring/PersistenceXmlConfig.java +++ b/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java @@ -1,4 +1,4 @@ -package org.baeldung.spring; +package com.baeldung.spring; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -7,7 +7,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @EnableTransactionManagement -@ComponentScan({ "org.baeldung.persistence.dao", "org.baeldung.persistence.service" }) +@ComponentScan({ "com.baeldung.persistence.dao", "com.baeldung.persistence.service" }) @ImportResource({ "classpath:hibernate4Config.xml" }) public class PersistenceXmlConfig { diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IChildDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IChildDao.java deleted file mode 100644 index 3bc0dc1fc4..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IChildDao.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.baeldung.persistence.dao; - -import org.baeldung.persistence.dao.common.IOperations; -import org.baeldung.persistence.model.Child; - -public interface IChildDao extends IOperations { - // -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IFooDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IFooDao.java deleted file mode 100644 index fc3928d8a6..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IFooDao.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.baeldung.persistence.dao; - -import org.baeldung.persistence.dao.common.IOperations; -import org.baeldung.persistence.model.Foo; - -public interface IFooDao extends IOperations { - // -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IParentDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IParentDao.java deleted file mode 100644 index 09158a4143..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/IParentDao.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.baeldung.persistence.dao; - -import org.baeldung.persistence.dao.common.IOperations; -import org.baeldung.persistence.model.Parent; - -public interface IParentDao extends IOperations { - // -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/ChildDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/ChildDao.java deleted file mode 100644 index 80a4007633..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/ChildDao.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.baeldung.persistence.dao.impl; - -import org.baeldung.persistence.dao.IChildDao; -import org.baeldung.persistence.dao.common.AbstractHibernateDao; -import org.baeldung.persistence.model.Child; -import org.springframework.stereotype.Repository; - -@Repository -public class ChildDao extends AbstractHibernateDaoimplements IChildDao { - - public ChildDao() { - super(); - - setClazz(Child.class); - } - - // API - -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/FooDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/FooDao.java deleted file mode 100644 index eb3a66126c..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/FooDao.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.baeldung.persistence.dao.impl; - -import org.baeldung.persistence.dao.IFooDao; -import org.baeldung.persistence.dao.common.AbstractHibernateDao; -import org.baeldung.persistence.model.Foo; -import org.springframework.stereotype.Repository; - -@Repository -public class FooDao extends AbstractHibernateDaoimplements IFooDao { - - public FooDao() { - super(); - - setClazz(Foo.class); - } - - // API - -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/ParentDao.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/ParentDao.java deleted file mode 100644 index fca4c69338..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/dao/impl/ParentDao.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.baeldung.persistence.dao.impl; - -import org.baeldung.persistence.dao.IParentDao; -import org.baeldung.persistence.dao.common.AbstractHibernateDao; -import org.baeldung.persistence.model.Parent; -import org.springframework.stereotype.Repository; - -@Repository -public class ParentDao extends AbstractHibernateDaoimplements IParentDao { - - public ParentDao() { - super(); - - setClazz(Parent.class); - } - - // API - -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Bar.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Bar.java deleted file mode 100644 index 410ad79b02..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/model/Bar.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.baeldung.persistence.model; - -import java.io.Serializable; -import java.util.Set; - -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.NamedQuery; -import javax.persistence.OneToMany; - -import org.hibernate.annotations.OrderBy; - -import com.google.common.collect.Sets; - -@Entity -@NamedQuery(name = "Bar.findAll", query = "SELECT b FROM Bar b") -public class Bar implements Serializable { - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - @Column(name = "id") - private int id; - - @Column(name = "name") - private String name; - - @OneToMany(mappedBy = "bar", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - @OrderBy(clause = "NAME DESC") - private Set fooSet = Sets.newHashSet(); - - public Bar() { - super(); - } - - public Bar(final String name) { - super(); - - this.name = name; - } - - // API - - public Set getFooSet() { - return fooSet; - } - - public void setFooSet(final Set fooSet) { - this.fooSet = fooSet; - } - - public int 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 + ((name == null) ? 0 : name.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final Bar other = (Bar) obj; - 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("Bar [name=").append(name).append("]"); - return builder.toString(); - } - -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IChildService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IChildService.java deleted file mode 100644 index c6c5e2cfb1..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IChildService.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.baeldung.persistence.service; - -import org.baeldung.persistence.dao.common.IOperations; -import org.baeldung.persistence.model.Child; - -public interface IChildService extends IOperations { - // -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IFooService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IFooService.java deleted file mode 100644 index 8774320450..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IFooService.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.baeldung.persistence.service; - -import org.baeldung.persistence.dao.common.IOperations; -import org.baeldung.persistence.model.Foo; - -public interface IFooService extends IOperations { - // -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IParentService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IParentService.java deleted file mode 100644 index 1782c281d2..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/IParentService.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.baeldung.persistence.service; - -import org.baeldung.persistence.dao.common.IOperations; -import org.baeldung.persistence.model.Parent; - -public interface IParentService extends IOperations { - // -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ChildService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ChildService.java deleted file mode 100644 index 71b1bc697e..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ChildService.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.baeldung.persistence.service.impl; - -import org.baeldung.persistence.dao.IChildDao; -import org.baeldung.persistence.dao.common.IOperations; -import org.baeldung.persistence.model.Child; -import org.baeldung.persistence.service.IChildService; -import org.baeldung.persistence.service.common.AbstractService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class ChildService extends AbstractServiceimplements IChildService { - - @Autowired - private IChildDao dao; - - public ChildService() { - super(); - } - - // API - - @Override - protected IOperations getDao() { - return dao; - } - -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/FooService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/FooService.java deleted file mode 100644 index 8a89153dd0..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/FooService.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.baeldung.persistence.service.impl; - -import org.baeldung.persistence.dao.IFooDao; -import org.baeldung.persistence.dao.common.IOperations; -import org.baeldung.persistence.model.Foo; -import org.baeldung.persistence.service.IFooService; -import org.baeldung.persistence.service.common.AbstractService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class FooService extends AbstractServiceimplements IFooService { - - @Autowired - private IFooDao dao; - - public FooService() { - super(); - } - - // API - - @Override - protected IOperations getDao() { - return dao; - } - -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ParentService.java b/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ParentService.java deleted file mode 100644 index 1f9b602350..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/persistence/service/impl/ParentService.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.baeldung.persistence.service.impl; - -import org.baeldung.persistence.dao.IParentDao; -import org.baeldung.persistence.dao.common.IOperations; -import org.baeldung.persistence.model.Parent; -import org.baeldung.persistence.service.IParentService; -import org.baeldung.persistence.service.common.AbstractService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class ParentService extends AbstractServiceimplements IParentService { - - @Autowired - private IParentDao dao; - - public ParentService() { - super(); - } - - // API - - @Override - protected IOperations getDao() { - return dao; - } - -} diff --git a/spring-hibernate4/src/main/java/org/baeldung/spring/PersistenceConfig.java b/spring-hibernate4/src/main/java/org/baeldung/spring/PersistenceConfig.java deleted file mode 100644 index 000c67d625..0000000000 --- a/spring-hibernate4/src/main/java/org/baeldung/spring/PersistenceConfig.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.baeldung.spring; - -import java.util.Properties; - -import javax.sql.DataSource; - -import org.apache.tomcat.dbcp.dbcp.BasicDataSource; -import org.hibernate.SessionFactory; -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.context.annotation.PropertySource; -import org.springframework.core.env.Environment; -import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; -import org.springframework.orm.hibernate4.HibernateTransactionManager; -import org.springframework.orm.hibernate4.LocalSessionFactoryBean; -import org.springframework.transaction.annotation.EnableTransactionManagement; - -import com.google.common.base.Preconditions; - -@Configuration -@EnableTransactionManagement -@PropertySource({ "classpath:persistence-mysql.properties" }) -@ComponentScan({ "org.baeldung.persistence" }) -public class PersistenceConfig { - - @Autowired - private Environment env; - - public PersistenceConfig() { - super(); - } - - @Bean - public LocalSessionFactoryBean sessionFactory() { - final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); - sessionFactory.setDataSource(restDataSource()); - sessionFactory.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); - sessionFactory.setHibernateProperties(hibernateProperties()); - - return sessionFactory; - } - - @Bean - public DataSource restDataSource() { - final BasicDataSource dataSource = new BasicDataSource(); - dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName"))); - dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url"))); - dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user"))); - dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass"))); - - return dataSource; - } - - @Bean - @Autowired - public HibernateTransactionManager transactionManager(final SessionFactory sessionFactory) { - final HibernateTransactionManager txManager = new HibernateTransactionManager(); - txManager.setSessionFactory(sessionFactory); - - return txManager; - } - - @Bean - public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { - return new PersistenceExceptionTranslationPostProcessor(); - } - - final Properties hibernateProperties() { - final Properties hibernateProperties = new Properties(); - hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); - hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); - - hibernateProperties.setProperty("hibernate.show_sql", "true"); - // hibernateProperties.setProperty("hibernate.format_sql", "true"); - // hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true"); - - return hibernateProperties; - } - -} \ No newline at end of file diff --git a/spring-hibernate4/src/main/resources/hibernate4Config.xml b/spring-hibernate4/src/main/resources/hibernate4Config.xml index aa419a19f7..ca507802cd 100644 --- a/spring-hibernate4/src/main/resources/hibernate4Config.xml +++ b/spring-hibernate4/src/main/resources/hibernate4Config.xml @@ -9,7 +9,7 @@ - + ${hibernate.hbm2ddl.auto} @@ -18,7 +18,7 @@ - + diff --git a/spring-hibernate4/src/main/resources/persistence-mysql.properties b/spring-hibernate4/src/main/resources/persistence-mysql.properties index 8263b0d9ac..f6b6ab6fca 100644 --- a/spring-hibernate4/src/main/resources/persistence-mysql.properties +++ b/spring-hibernate4/src/main/resources/persistence-mysql.properties @@ -8,3 +8,6 @@ jdbc.pass=tutorialmy5ql hibernate.dialect=org.hibernate.dialect.MySQL5Dialect hibernate.show_sql=false hibernate.hbm2ddl.auto=create-drop + +# envers.X +envers.audit_table_suffix=_audit_log diff --git a/spring-hibernate4/src/main/resources/webSecurityConfig.xml b/spring-hibernate4/src/main/resources/webSecurityConfig.xml index 88af78dabc..d9423d31e7 100644 --- a/spring-hibernate4/src/main/resources/webSecurityConfig.xml +++ b/spring-hibernate4/src/main/resources/webSecurityConfig.xml @@ -5,7 +5,8 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd" > - + + diff --git a/spring-hibernate4/src/test/java/org/baeldung/persistence/IntegrationTestSuite.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java similarity index 59% rename from spring-hibernate4/src/test/java/org/baeldung/persistence/IntegrationTestSuite.java rename to spring-hibernate4/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java index 42fcc28378..c107a221d6 100644 --- a/spring-hibernate4/src/test/java/org/baeldung/persistence/IntegrationTestSuite.java +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java @@ -1,10 +1,10 @@ -package org.baeldung.persistence; +package com.baeldung.persistence; -import org.baeldung.persistence.hibernate.FooPaginationPersistenceIntegrationTest; -import org.baeldung.persistence.hibernate.FooSortingPersistenceServiceTest; -import org.baeldung.persistence.service.FooServiceBasicPersistenceIntegrationTest; -import org.baeldung.persistence.service.FooServicePersistenceIntegrationTest; -import org.baeldung.persistence.service.ParentServicePersistenceIntegrationTest; +import com.baeldung.persistence.hibernate.FooPaginationPersistenceIntegrationTest; +import com.baeldung.persistence.hibernate.FooSortingPersistenceServiceTest; +import com.baeldung.persistence.service.FooServicePersistenceIntegrationTest; +import com.baeldung.persistence.service.FooServiceBasicPersistenceIntegrationTest; +import com.baeldung.persistence.service.ParentServicePersistenceIntegrationTest; import org.junit.runner.RunWith; import org.junit.runners.Suite; diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java new file mode 100644 index 0000000000..8a8a3445f6 --- /dev/null +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java @@ -0,0 +1,14 @@ +package com.baeldung.persistence.audit; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ // @formatter:off + EnversFooBarAuditTest.class, + JPABarAuditTest.class, + SpringDataJPABarAuditTest.class +}) // @formatter:on +public class AuditTestSuite { + // +} \ No newline at end of file diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditTest.java new file mode 100644 index 0000000000..6c13816b63 --- /dev/null +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditTest.java @@ -0,0 +1,142 @@ +package com.baeldung.persistence.audit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.List; + +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.service.IBarAuditableService; +import com.baeldung.persistence.service.IFooAuditableService; +import com.baeldung.spring.PersistenceConfig; +import com.baeldung.persistence.model.Bar; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +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.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class EnversFooBarAuditTest { + + private static Logger logger = LoggerFactory.getLogger(EnversFooBarAuditTest.class); + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + logger.info("setUpBeforeClass()"); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + logger.info("tearDownAfterClass()"); + } + + @Autowired + @Qualifier("fooHibernateAuditableService") + private IFooAuditableService fooService; + + @Autowired + @Qualifier("barHibernateAuditableService") + private IBarAuditableService barService; + + @Autowired + private SessionFactory sessionFactory; + + private Session session; + + @Before + public void setUp() throws Exception { + logger.info("setUp()"); + makeRevisions(); + session = sessionFactory.openSession(); + } + + @After + public void tearDown() throws Exception { + logger.info("tearDown()"); + session.close(); + } + + private void makeRevisions() { + final Bar bar = rev1(); + rev2(bar); + rev3(bar); + rev4(bar); + } + + // REV #1: insert BAR & FOO1 + private Bar rev1() { + final Bar bar = new Bar("BAR"); + final Foo foo1 = new Foo("FOO1"); + foo1.setBar(bar); + fooService.create(foo1); + return bar; + } + + // REV #2: insert FOO2 & update BAR + private void rev2(final Bar bar) { + final Foo foo2 = new Foo("FOO2"); + foo2.setBar(bar); + fooService.create(foo2); + } + + // REV #3: update BAR + private void rev3(final Bar bar) { + + bar.setName("BAR1"); + barService.update(bar); + } + + // REV #4: insert FOO3 & update BAR + private void rev4(final Bar bar) { + + final Foo foo3 = new Foo("FOO3"); + foo3.setBar(bar); + fooService.create(foo3); + } + + @Test + public final void whenFooBarsModified_thenFooBarsAudited() { + + List barRevisionList; + List fooRevisionList; + + // test Bar revisions + + barRevisionList = barService.getRevisions(); + + assertNotNull(barRevisionList); + assertEquals(4, barRevisionList.size()); + + assertEquals("BAR", barRevisionList.get(0).getName()); + assertEquals("BAR", barRevisionList.get(1).getName()); + assertEquals("BAR1", barRevisionList.get(2).getName()); + assertEquals("BAR1", barRevisionList.get(3).getName()); + + assertEquals(1, barRevisionList.get(0).getFooSet().size()); + assertEquals(2, barRevisionList.get(1).getFooSet().size()); + assertEquals(2, barRevisionList.get(2).getFooSet().size()); + assertEquals(3, barRevisionList.get(3).getFooSet().size()); + + // test Foo revisions + + fooRevisionList = fooService.getRevisions(); + assertNotNull(fooRevisionList); + assertEquals(3, fooRevisionList.size()); + assertEquals("FOO1", fooRevisionList.get(0).getName()); + assertEquals("FOO2", fooRevisionList.get(1).getName()); + assertEquals("FOO3", fooRevisionList.get(2).getName()); + } + +} diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/JPABarAuditTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/JPABarAuditTest.java new file mode 100644 index 0000000000..1e4a10f61c --- /dev/null +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/JPABarAuditTest.java @@ -0,0 +1,102 @@ +package com.baeldung.persistence.audit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; + +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.model.Bar.OPERATION; +import com.baeldung.persistence.service.IBarService; +import com.baeldung.spring.PersistenceConfig; +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.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class JPABarAuditTest { + + private static Logger logger = LoggerFactory.getLogger(JPABarAuditTest.class); + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + logger.info("setUpBeforeClass()"); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + logger.info("tearDownAfterClass()"); + } + + @Autowired + @Qualifier("barJpaService") + private IBarService barService; + + @Autowired + private EntityManagerFactory entityManagerFactory; + + private EntityManager em; + + @Before + public void setUp() throws Exception { + logger.info("setUp()"); + em = entityManagerFactory.createEntityManager(); + } + + @After + public void tearDown() throws Exception { + logger.info("tearDown()"); + em.close(); + } + + @Test + public final void whenBarsModified_thenBarsAudited() { + + // insert BAR1 + Bar bar1 = new Bar("BAR1"); + barService.create(bar1); + + // update BAR1 + bar1.setName("BAR1a"); + barService.update(bar1); + + // insert BAR2 + Bar bar2 = new Bar("BAR2"); + barService.create(bar2); + + // update BAR1 + bar1.setName("BAR1b"); + barService.update(bar1); + + // get BAR1 and BAR2 from the DB and check the audit values + // detach instances from persistence context to make sure we fire db + em.detach(bar1); + em.detach(bar2); + bar1 = barService.findOne(bar1.getId()); + bar2 = barService.findOne(bar2.getId()); + + assertNotNull(bar1); + assertNotNull(bar2); + assertEquals(OPERATION.UPDATE, bar1.getOperation()); + assertEquals(OPERATION.INSERT, bar2.getOperation()); + assertTrue(bar1.getTimestamp() > bar2.getTimestamp()); + + barService.deleteById(bar1.getId()); + barService.deleteById(bar2.getId()); + + } + +} \ No newline at end of file diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditTest.java new file mode 100644 index 0000000000..05c0e9fa83 --- /dev/null +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditTest.java @@ -0,0 +1,76 @@ +package com.baeldung.persistence.audit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; + +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.service.IBarService; +import com.baeldung.spring.PersistenceConfig; +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.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +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.support.AnnotationConfigContextLoader; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +public class SpringDataJPABarAuditTest { + + private static Logger logger = LoggerFactory.getLogger(SpringDataJPABarAuditTest.class); + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + logger.info("setUpBeforeClass()"); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + logger.info("tearDownAfterClass()"); + } + + @Autowired + @Qualifier("barSpringDataJpaService") + private IBarService barService; + + @Autowired + private EntityManagerFactory entityManagerFactory; + + private EntityManager em; + + @Before + public void setUp() throws Exception { + logger.info("setUp()"); + em = entityManagerFactory.createEntityManager(); + } + + @After + public void tearDown() throws Exception { + logger.info("tearDown()"); + em.close(); + } + + @Test + @WithMockUser(username = "tutorialuser") + public final void whenBarsModified_thenBarsAudited() { + Bar bar = new Bar("BAR1"); + barService.create(bar); + assertEquals(bar.getCreatedDate(), bar.getModifiedDate()); + assertEquals("tutorialuser", bar.getCreatedBy(), bar.getModifiedBy()); + bar.setName("BAR2"); + bar = barService.update(bar); + assertTrue(bar.getCreatedDate() < bar.getModifiedDate()); + assertEquals("tutorialuser", bar.getCreatedBy(), bar.getModifiedBy()); + } +} diff --git a/spring-hibernate4/src/test/java/org/baeldung/persistence/hibernate/FooFixtures.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java similarity index 95% rename from spring-hibernate4/src/test/java/org/baeldung/persistence/hibernate/FooFixtures.java rename to spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java index 8b16f9b605..da840dc027 100644 --- a/spring-hibernate4/src/test/java/org/baeldung/persistence/hibernate/FooFixtures.java +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java @@ -1,9 +1,9 @@ -package org.baeldung.persistence.hibernate; +package com.baeldung.persistence.hibernate; import java.util.List; -import org.baeldung.persistence.model.Bar; -import org.baeldung.persistence.model.Foo; +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.model.Bar; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; diff --git a/spring-hibernate4/src/test/java/org/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java similarity index 96% rename from spring-hibernate4/src/test/java/org/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java rename to spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java index 37e77ef139..20bbf72243 100644 --- a/spring-hibernate4/src/test/java/org/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java @@ -1,4 +1,4 @@ -package org.baeldung.persistence.hibernate; +package com.baeldung.persistence.hibernate; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.hamcrest.Matchers.hasSize; @@ -7,9 +7,9 @@ import static org.junit.Assert.assertThat; import java.util.List; -import org.baeldung.persistence.model.Foo; -import org.baeldung.persistence.service.IFooService; -import org.baeldung.spring.PersistenceConfig; +import com.baeldung.persistence.model.Foo; +import com.baeldung.persistence.service.IFooService; +import com.baeldung.spring.PersistenceConfig; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.ScrollMode; diff --git a/spring-hibernate4/src/test/java/org/baeldung/persistence/hibernate/FooSortingPersistenceServiceTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceServiceTest.java similarity index 97% rename from spring-hibernate4/src/test/java/org/baeldung/persistence/hibernate/FooSortingPersistenceServiceTest.java rename to spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceServiceTest.java index 3e600816f5..c890e08d15 100644 --- a/spring-hibernate4/src/test/java/org/baeldung/persistence/hibernate/FooSortingPersistenceServiceTest.java +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceServiceTest.java @@ -1,13 +1,13 @@ -package org.baeldung.persistence.hibernate; +package com.baeldung.persistence.hibernate; import static org.junit.Assert.assertNull; import java.util.List; import java.util.Set; -import org.baeldung.persistence.model.Bar; -import org.baeldung.persistence.model.Foo; -import org.baeldung.spring.PersistenceConfig; +import com.baeldung.persistence.model.Bar; +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.PersistenceConfig; import org.hibernate.Criteria; import org.hibernate.NullPrecedence; import org.hibernate.Query; diff --git a/spring-hibernate4/src/test/java/org/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java similarity index 87% rename from spring-hibernate4/src/test/java/org/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java rename to spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java index 2865810c67..c77f5dfb95 100644 --- a/spring-hibernate4/src/test/java/org/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java @@ -1,10 +1,9 @@ -package org.baeldung.persistence.service; +package com.baeldung.persistence.service; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; -import org.baeldung.persistence.model.Foo; -import org.baeldung.persistence.service.IFooService; -import org.baeldung.spring.PersistenceConfig; +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.PersistenceConfig; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.junit.After; diff --git a/spring-hibernate4/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java similarity index 89% rename from spring-hibernate4/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java rename to spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java index 07c6ba3382..b82d4621ab 100644 --- a/spring-hibernate4/src/test/java/org/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java @@ -1,13 +1,14 @@ -package org.baeldung.persistence.service; +package com.baeldung.persistence.service; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; -import org.baeldung.persistence.model.Foo; -import org.baeldung.spring.PersistenceConfig; +import com.baeldung.persistence.model.Foo; +import com.baeldung.spring.PersistenceConfig; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.InvalidDataAccessApiUsageException; @@ -20,6 +21,7 @@ import org.springframework.test.context.support.AnnotationConfigContextLoader; public class FooServicePersistenceIntegrationTest { @Autowired + @Qualifier("fooHibernateService") private IFooService service; // tests diff --git a/spring-hibernate4/src/test/java/org/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java similarity index 92% rename from spring-hibernate4/src/test/java/org/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java rename to spring-hibernate4/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java index 3960aa79ea..9e8c4aba92 100644 --- a/spring-hibernate4/src/test/java/org/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java @@ -1,8 +1,8 @@ -package org.baeldung.persistence.service; +package com.baeldung.persistence.service; -import org.baeldung.persistence.model.Child; -import org.baeldung.persistence.model.Parent; -import org.baeldung.spring.PersistenceConfig; +import com.baeldung.persistence.model.Child; +import com.baeldung.persistence.model.Parent; +import com.baeldung.spring.PersistenceConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-jpa/pom.xml b/spring-jpa/pom.xml index 20be07ca5b..2e8f818776 100644 --- a/spring-jpa/pom.xml +++ b/spring-jpa/pom.xml @@ -186,7 +186,7 @@ 4.3.11.Final 5.1.37 - 1.7.2.RELEASE + 1.8.2.RELEASE 1.7.13 diff --git a/spring-jpa/src/main/java/org/baeldung/persistence/dao/FooDao.java b/spring-jpa/src/main/java/org/baeldung/persistence/dao/FooDao.java index becd8d5f67..77978c5cf2 100644 --- a/spring-jpa/src/main/java/org/baeldung/persistence/dao/FooDao.java +++ b/spring-jpa/src/main/java/org/baeldung/persistence/dao/FooDao.java @@ -4,7 +4,7 @@ import org.baeldung.persistence.model.Foo; import org.springframework.stereotype.Repository; @Repository -public class FooDao extends AbstractJpaDAOimplements IFooDao { +public class FooDao extends AbstractJpaDAO implements IFooDao { public FooDao() { super(); diff --git a/spring-katharsis/src/main/java/org/baeldung/persistence/model/User.java b/spring-katharsis/src/main/java/org/baeldung/persistence/model/User.java index 58a92002c8..67e4c6ae1d 100644 --- a/spring-katharsis/src/main/java/org/baeldung/persistence/model/User.java +++ b/spring-katharsis/src/main/java/org/baeldung/persistence/model/User.java @@ -30,7 +30,7 @@ public class User { private String email; @ManyToMany(fetch = FetchType.EAGER) - @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) + @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id") , inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id") ) @JsonApiToMany @JsonApiIncludeByDefault private Set roles; diff --git a/spring-mvc-java/src/main/java/org/baeldung/aop/LoggingAspect.java b/spring-mvc-java/src/main/java/org/baeldung/aop/LoggingAspect.java index 72ac610abd..c59c4f060a 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/aop/LoggingAspect.java +++ b/spring-mvc-java/src/main/java/org/baeldung/aop/LoggingAspect.java @@ -24,13 +24,16 @@ public class LoggingAspect { }; @Pointcut("@target(org.springframework.stereotype.Repository)") - public void repositoryMethods() {} + public void repositoryMethods() { + } @Pointcut("@annotation(org.baeldung.aop.annotations.Loggable)") - public void loggableMethods() {} + public void loggableMethods() { + } @Pointcut("@args(org.baeldung.aop.annotations.Entity)") - public void methodsAcceptingEntities() {} + public void methodsAcceptingEntities() { + } @Before("repositoryMethods()") public void logMethodCall(JoinPoint jp) { diff --git a/spring-mvc-java/src/main/java/org/baeldung/aop/PerformanceAspect.java b/spring-mvc-java/src/main/java/org/baeldung/aop/PerformanceAspect.java index 57f5bc5edd..2d07e5a5f3 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/aop/PerformanceAspect.java +++ b/spring-mvc-java/src/main/java/org/baeldung/aop/PerformanceAspect.java @@ -16,7 +16,8 @@ public class PerformanceAspect { private static Logger logger = Logger.getLogger(PerformanceAspect.class.getName()); @Pointcut("within(@org.springframework.stereotype.Repository *)") - public void repositoryClassMethods() {} + public void repositoryClassMethods() { + } @Around("repositoryClassMethods()") public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable { diff --git a/spring-mvc-java/src/main/java/org/baeldung/aop/PublishingAspect.java b/spring-mvc-java/src/main/java/org/baeldung/aop/PublishingAspect.java index 20a10f4f6a..324605dab1 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/aop/PublishingAspect.java +++ b/spring-mvc-java/src/main/java/org/baeldung/aop/PublishingAspect.java @@ -21,13 +21,16 @@ public class PublishingAspect { } @Pointcut("@target(org.springframework.stereotype.Repository)") - public void repositoryMethods() {} + public void repositoryMethods() { + } @Pointcut("execution(* *..create*(Long,..))") - public void firstLongParamMethods() {} + public void firstLongParamMethods() { + } @Pointcut("repositoryMethods() && firstLongParamMethods()") - public void entityCreationMethods() {} + public void entityCreationMethods() { + } @AfterReturning(value = "entityCreationMethods()", returning = "entity") public void logMethodCall(JoinPoint jp, Object entity) throws Throwable { diff --git a/spring-mvc-java/src/main/java/org/baeldung/model/Foo.java b/spring-mvc-java/src/main/java/org/baeldung/model/Foo.java index 0b1a553afc..87bd7132e6 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/model/Foo.java +++ b/spring-mvc-java/src/main/java/org/baeldung/model/Foo.java @@ -14,9 +14,6 @@ public class Foo { @Override public String toString() { - return "Foo{" + - "id=" + id + - ", name='" + name + '\'' + - '}'; + return "Foo{" + "id=" + id + ", name='" + name + '\'' + '}'; } } diff --git a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/WebConfig.java b/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/WebConfig.java index d60bcfe127..09e9cff917 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/WebConfig.java +++ b/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/WebConfig.java @@ -1,9 +1,17 @@ package org.baeldung.spring.web.config; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; +import org.springframework.web.servlet.view.ResourceBundleViewResolver; +import org.springframework.web.servlet.view.XmlViewResolver; @Configuration @EnableWebMvc @@ -14,6 +22,38 @@ public class WebConfig extends WebMvcConfigurerAdapter { super(); } - // API + // + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/sample.html"); + } + + @Bean + public ViewResolver internalResourceViewResolver() { + final InternalResourceViewResolver bean = new InternalResourceViewResolver(); + bean.setViewClass(JstlView.class); + bean.setPrefix("/WEB-INF/view/"); + bean.setSuffix(".jsp"); + bean.setOrder(2); + return bean; + } + + @Bean + public ViewResolver xmlViewResolver() { + final XmlViewResolver bean = new XmlViewResolver(); + bean.setLocation(new ClassPathResource("views.xml")); + bean.setOrder(1); + return bean; + } + + @Bean + public ViewResolver resourceBundleViewResolver() { + final ResourceBundleViewResolver bean = new ResourceBundleViewResolver(); + bean.setBasename("views"); + bean.setOrder(0); + return bean; + } } \ No newline at end of file diff --git a/spring-mvc-java/src/main/java/org/baeldung/web/controller/UserController.java b/spring-mvc-java/src/main/java/org/baeldung/web/controller/UserController.java index 731424c336..da39a36adf 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/web/controller/UserController.java +++ b/spring-mvc-java/src/main/java/org/baeldung/web/controller/UserController.java @@ -13,20 +13,19 @@ public class UserController { @RequestMapping(value = "/", method = RequestMethod.GET) public String showForm(final Model model) { - final User user = new User(); - user.setFirstname("John"); - user.setLastname("Roy"); - user.setEmailId("John.Roy@gmail.com"); - model.addAttribute("user", user); - return "index"; + final User user = new User(); + user.setFirstname("John"); + user.setLastname("Roy"); + user.setEmailId("John.Roy@gmail.com"); + model.addAttribute("user", user); + return "index"; } @RequestMapping(value = "/processForm", method = RequestMethod.POST) - public String processForm(@ModelAttribute(value = "user") final User user, - final Model model) { - // Insert User into DB - model.addAttribute("name", user.getFirstname() + " " + user.getLastname()); - return "hello"; + public String processForm(@ModelAttribute(value = "user") final User user, final Model model) { + // Insert User into DB + model.addAttribute("name", user.getFirstname() + " " + user.getLastname()); + return "hello"; } } diff --git a/spring-mvc-java/src/main/resources/views.properties b/spring-mvc-java/src/main/resources/views.properties new file mode 100644 index 0000000000..95687cb62a --- /dev/null +++ b/spring-mvc-java/src/main/resources/views.properties @@ -0,0 +1,3 @@ +sample.(class)=org.springframework.web.servlet.view.JstlView +sample.url=/WEB-INF/view/sample.jsp + diff --git a/spring-mvc-java/src/main/resources/views.xml b/spring-mvc-java/src/main/resources/views.xml new file mode 100644 index 0000000000..83bca5293d --- /dev/null +++ b/spring-mvc-java/src/main/resources/views.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/spring-mvc-java/src/test/java/org/baeldung/aop/AopLoggingTest.java b/spring-mvc-java/src/test/java/org/baeldung/aop/AopLoggingTest.java index 4c8fcd50a8..b1c9867e41 100644 --- a/spring-mvc-java/src/test/java/org/baeldung/aop/AopLoggingTest.java +++ b/spring-mvc-java/src/test/java/org/baeldung/aop/AopLoggingTest.java @@ -24,12 +24,12 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = {TestConfig.class}, loader = AnnotationConfigContextLoader.class) +@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) public class AopLoggingTest { @Before public void setUp() { - messages = new ArrayList<>(); + messages = new ArrayList<>(); logEventHandler = new Handler() { @Override diff --git a/spring-mvc-java/src/test/java/org/baeldung/aop/AopPerformanceTest.java b/spring-mvc-java/src/test/java/org/baeldung/aop/AopPerformanceTest.java index 82af95957a..69083c60a2 100644 --- a/spring-mvc-java/src/test/java/org/baeldung/aop/AopPerformanceTest.java +++ b/spring-mvc-java/src/test/java/org/baeldung/aop/AopPerformanceTest.java @@ -23,7 +23,7 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = {TestConfig.class}, loader = AnnotationConfigContextLoader.class) +@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) public class AopPerformanceTest { @Before diff --git a/spring-mvc-java/src/test/java/org/baeldung/aop/AopPublishingTest.java b/spring-mvc-java/src/test/java/org/baeldung/aop/AopPublishingTest.java index 561eec06ec..e691dbd32e 100644 --- a/spring-mvc-java/src/test/java/org/baeldung/aop/AopPublishingTest.java +++ b/spring-mvc-java/src/test/java/org/baeldung/aop/AopPublishingTest.java @@ -22,7 +22,7 @@ import java.util.regex.Pattern; import static org.junit.Assert.assertTrue; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = {TestConfig.class}, loader = AnnotationConfigContextLoader.class) +@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) public class AopPublishingTest { @Before @@ -60,8 +60,7 @@ public class AopPublishingTest { dao.create(1L, "Bar"); String logMessage = messages.get(0); - Pattern pattern = Pattern.compile("Created foo instance: " + - Pattern.quote(new Foo(1L, "Bar").toString())); + Pattern pattern = Pattern.compile("Created foo instance: " + Pattern.quote(new Foo(1L, "Bar").toString())); assertTrue(pattern.matcher(logMessage).matches()); } } diff --git a/spring-mvc-java/src/test/java/org/baeldung/config/TestConfig.java b/spring-mvc-java/src/test/java/org/baeldung/config/TestConfig.java index 0d103f1029..f9573b2add 100644 --- a/spring-mvc-java/src/test/java/org/baeldung/config/TestConfig.java +++ b/spring-mvc-java/src/test/java/org/baeldung/config/TestConfig.java @@ -5,7 +5,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration -@ComponentScan(basePackages = {"org.baeldung.dao", "org.baeldung.aop", "org.baeldung.events"}) +@ComponentScan(basePackages = { "org.baeldung.dao", "org.baeldung.aop", "org.baeldung.events" }) @EnableAspectJAutoProxy public class TestConfig { } diff --git a/spring-rest/pom.xml b/spring-rest/pom.xml index e2cf9d7c3e..54ac868b95 100644 --- a/spring-rest/pom.xml +++ b/spring-rest/pom.xml @@ -33,7 +33,6 @@ org.springframework spring-web - ${org.springframework.version} commons-logging @@ -44,12 +43,10 @@ org.springframework spring-webmvc - ${org.springframework.version} org.springframework spring-oxm - ${org.springframework.version} @@ -229,7 +226,6 @@ - 4.2.4.RELEASE 4.0.3.RELEASE diff --git a/spring-rest/src/main/java/org/baeldung/web/controller/status/ExampleController.java b/spring-rest/src/main/java/org/baeldung/web/controller/status/ExampleController.java new file mode 100644 index 0000000000..ceda138768 --- /dev/null +++ b/spring-rest/src/main/java/org/baeldung/web/controller/status/ExampleController.java @@ -0,0 +1,24 @@ +package org.baeldung.web.controller.status; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class ExampleController { + + @RequestMapping(value = "/controller", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity sendViaResponseEntity() { + return new ResponseEntity(HttpStatus.NOT_ACCEPTABLE); + } + + @RequestMapping(value = "/exception", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity sendViaException() { + throw new ForbiddenException(); + } +} diff --git a/spring-rest/src/main/java/org/baeldung/web/controller/status/ForbiddenException.java b/spring-rest/src/main/java/org/baeldung/web/controller/status/ForbiddenException.java new file mode 100644 index 0000000000..1d4aff2ebf --- /dev/null +++ b/spring-rest/src/main/java/org/baeldung/web/controller/status/ForbiddenException.java @@ -0,0 +1,9 @@ +package org.baeldung.web.controller.status; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@ResponseStatus(value = HttpStatus.FORBIDDEN, reason="To show an example of a custom message") +public class ForbiddenException extends RuntimeException { + +} diff --git a/spring-rest/src/test/java/org/baeldung/web/controller/status/ExampleControllerTest.java b/spring-rest/src/test/java/org/baeldung/web/controller/status/ExampleControllerTest.java new file mode 100644 index 0000000000..1344d2d40e --- /dev/null +++ b/spring-rest/src/test/java/org/baeldung/web/controller/status/ExampleControllerTest.java @@ -0,0 +1,44 @@ +package org.baeldung.web.controller.status; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.baeldung.config.WebConfig; +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.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = WebConfig.class) +@WebAppConfiguration +public class ExampleControllerTest { + + private MockMvc mockMvc; + + @Autowired + private WebApplicationContext webApplicationContext; + + @Before + public void setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); + } + + @Test + public void whenGetRequestSentToController_thenReturnsStatusNotAcceptable() throws Exception { + mockMvc.perform(get("/controller")) + .andExpect(status().isNotAcceptable()); + } + + @Test + public void whenGetRequestSentToException_thenReturnsStatusForbidden() throws Exception { + mockMvc.perform(get("/exception")) + .andExpect(status().isForbidden()); + } +} diff --git a/spring-security-login-and-registration/pom.xml b/spring-security-login-and-registration/pom.xml index 9e0f15688f..f5b62be553 100644 --- a/spring-security-login-and-registration/pom.xml +++ b/spring-security-login-and-registration/pom.xml @@ -329,7 +329,7 @@ 1 - 1.8.0.RELEASE + 1.8.2.RELEASE 19.0 diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordMatches.java b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordMatches.java index 1e3193b7b5..fcc7e228a7 100644 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordMatches.java +++ b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/PasswordMatches.java @@ -19,8 +19,8 @@ public @interface PasswordMatches { String message() default "Passwords don't match"; - Class[]groups() default {}; + Class[] groups() default {}; - Class[]payload() default {}; + Class[] payload() default {}; } diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidEmail.java b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidEmail.java index b5dc4f0f46..a520a45b0c 100644 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidEmail.java +++ b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidEmail.java @@ -20,7 +20,7 @@ public @interface ValidEmail { String message() default "Invalid Email"; - Class[]groups() default {}; + Class[] groups() default {}; - Class[]payload() default {}; + Class[] payload() default {}; } diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidPassword.java b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidPassword.java index 5b92f4d133..37b217213a 100644 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidPassword.java +++ b/spring-security-login-and-registration/src/main/java/org/baeldung/validation/ValidPassword.java @@ -20,8 +20,8 @@ public @interface ValidPassword { String message() default "Invalid Password"; - Class[]groups() default {}; + Class[] groups() default {}; - Class[]payload() default {}; + Class[] payload() default {}; } diff --git a/spring-security-mvc-ldap/pom.xml b/spring-security-mvc-ldap/pom.xml index 3f9b9ad1ed..317c8dfb73 100644 --- a/spring-security-mvc-ldap/pom.xml +++ b/spring-security-mvc-ldap/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.3.1.RELEASE + 1.3.2.RELEASE diff --git a/spring-security-rest-custom/pom.xml b/spring-security-rest-custom/pom.xml index a112fdcd43..df936353d9 100644 --- a/spring-security-rest-custom/pom.xml +++ b/spring-security-rest-custom/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.3.1.RELEASE + 1.3.2.RELEASE diff --git a/spring-security-rest-full/.springBeans b/spring-security-rest-full/.springBeans index d11fb034bd..78c6703708 100644 --- a/spring-security-rest-full/.springBeans +++ b/spring-security-rest-full/.springBeans @@ -1,14 +1,18 @@ 1 - + src/main/webapp/WEB-INF/api-servlet.xml + java:org.baeldung.spring.SecurityWithoutCsrfConfig + + java:org.baeldung.spring.Application + diff --git a/spring-security-rest-full/pom.xml b/spring-security-rest-full/pom.xml index cbcc3fca64..270774ee13 100644 --- a/spring-security-rest-full/pom.xml +++ b/spring-security-rest-full/pom.xml @@ -10,7 +10,7 @@ org.springframework.boot spring-boot-starter-parent - 1.3.1.RELEASE + 1.3.2.RELEASE @@ -92,13 +92,11 @@ org.springframework spring-webmvc - - - org.springframework.data - spring-data-commons - - - + + + org.springframework.data + spring-data-commons + @@ -239,6 +237,11 @@ test + + org.springframework.security + spring-security-test + + junit junit @@ -430,11 +433,11 @@ 4.3.11.Final 5.1.37 - 1.7.2.RELEASE + 1.8.2.RELEASE 2.0.0 3.6.2 - + 2.5.5 1.4.01 diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java index c449cde8e2..533c0f5082 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/service/impl/FooService.java @@ -16,7 +16,7 @@ import com.google.common.collect.Lists; @Service @Transactional -public class FooService extends AbstractServiceimplements IFooService { +public class FooService extends AbstractService implements IFooService { @Autowired private IFooDao dao; diff --git a/spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithCsrfConfig.java b/spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithCsrfConfig.java new file mode 100644 index 0000000000..c2a21c3f9e --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithCsrfConfig.java @@ -0,0 +1,54 @@ +package org.baeldung.spring; + +import org.baeldung.web.error.CustomAccessDeniedHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +// @Configuration +// @EnableAutoConfiguration +// @EnableWebSecurity +// @EnableGlobalMethodSecurity(prePostEnabled = true) +public class SecurityWithCsrfConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private CustomAccessDeniedHandler accessDeniedHandler; + + public SecurityWithCsrfConfig() { + super(); + } + + // java config + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication().withUser("user1").password("user1Pass").authorities("ROLE_USER").and().withUser("admin").password("adminPass").authorities("ROLE_ADMIN"); + } + + @Override + public void configure(final WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + // @formatter:off + http + .authorizeRequests() + .antMatchers("/admin/*").hasAnyRole("ROLE_ADMIN") + .anyRequest().authenticated() + .and() + .httpBasic() + .and() + .exceptionHandling().accessDeniedHandler(accessDeniedHandler) + ; + // @formatter:on + } + +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/spring/SecSecurityConfig.java b/spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithoutCsrfConfig.java similarity index 94% rename from spring-security-rest-full/src/main/java/org/baeldung/spring/SecSecurityConfig.java rename to spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithoutCsrfConfig.java index 75daacbb04..6e3974f86d 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/spring/SecSecurityConfig.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/spring/SecurityWithoutCsrfConfig.java @@ -17,12 +17,12 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) // @ImportResource({ "classpath:webSecurityConfig.xml" }) -public class SecSecurityConfig extends WebSecurityConfigurerAdapter { +public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomAccessDeniedHandler accessDeniedHandler; - public SecSecurityConfig() { + public SecurityWithoutCsrfConfig() { super(); } 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 19780b1068..143e52d94e 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 @@ -31,6 +31,7 @@ public class WebConfig extends WebMvcConfigurerAdapter { public void addViewControllers(final ViewControllerRegistry registry) { super.addViewControllers(registry); registry.addViewController("/graph.html"); + registry.addViewController("/csrfHome.html"); } } \ No newline at end of file diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/BankController.java b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/BankController.java new file mode 100644 index 0000000000..1a4322c611 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/BankController.java @@ -0,0 +1,32 @@ +package org.baeldung.web.controller; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +// to test csrf +@Controller +public class BankController { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @RequestMapping(value = "/transfer", method = RequestMethod.GET) + @ResponseBody + public int transfer(@RequestParam("accountNo") final int accountNo, @RequestParam("amount") final int amount) { + logger.info("Transfer to {}", accountNo); + return amount; + } + + // write - just for test + @RequestMapping(value = "/transfer", method = RequestMethod.POST) + @ResponseStatus(HttpStatus.OK) + public void create(@RequestParam("accountNo") final int accountNo, @RequestParam("amount") final int amount) { + logger.info("Transfer to {}", accountNo); + + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/error/CustomAccessDeniedHandler.java b/spring-security-rest-full/src/main/java/org/baeldung/web/error/CustomAccessDeniedHandler.java index ae7340ef88..cc07417427 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/error/CustomAccessDeniedHandler.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/error/CustomAccessDeniedHandler.java @@ -16,6 +16,7 @@ public class CustomAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(final HttpServletRequest request, final HttpServletResponse response, final AccessDeniedException ex) throws IOException, ServletException { response.getOutputStream().print("Error Message Goes Here"); + response.setStatus(403); // response.sendRedirect("/my-error-page"); } diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java b/spring-security-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java index d0ed765c68..fec03d1ddb 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/metric/ActuatorMetricService.java @@ -27,7 +27,6 @@ public class ActuatorMetricService implements IActuatorMetricService { statusList = new ArrayList(); } - @Override public Object[][] getGraphData() { final Date current = new Date(); diff --git a/spring-security-rest-full/src/main/webapp/WEB-INF/view/csrfHome.jsp b/spring-security-rest-full/src/main/webapp/WEB-INF/view/csrfHome.jsp new file mode 100644 index 0000000000..6e6330bad4 --- /dev/null +++ b/spring-security-rest-full/src/main/webapp/WEB-INF/view/csrfHome.jsp @@ -0,0 +1,15 @@ + + + + +

CSRF test on Origin

+ Transfer Money to John + +
+ + + + +
+ + \ No newline at end of file diff --git a/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfAbstractIntegrationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfAbstractIntegrationTest.java new file mode 100644 index 0000000000..a94dd554f1 --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfAbstractIntegrationTest.java @@ -0,0 +1,48 @@ +package org.baeldung.csrf; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user; + +import javax.servlet.Filter; + +import org.baeldung.persistence.model.Foo; +import org.junit.Before; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +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.request.RequestPostProcessor; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +public class CsrfAbstractIntegrationTest { + + @Autowired + private WebApplicationContext context; + + @Autowired + private Filter springSecurityFilterChain; + + protected MockMvc mvc; + + // + + @Before + public void setup() { + mvc = MockMvcBuilders.webAppContextSetup(context).addFilters(springSecurityFilterChain).build(); + } + + protected RequestPostProcessor testUser() { + return user("user").password("userPass").roles("USER"); + } + + protected String createFoo() throws JsonProcessingException { + return new ObjectMapper().writeValueAsString(new Foo(randomAlphabetic(6))); + } +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfDisabledIntegrationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfDisabledIntegrationTest.java new file mode 100644 index 0000000000..d223e89fe0 --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfDisabledIntegrationTest.java @@ -0,0 +1,26 @@ +package org.baeldung.csrf; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.baeldung.spring.PersistenceConfig; +import org.baeldung.spring.SecurityWithoutCsrfConfig; +import org.baeldung.spring.WebConfig; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = { SecurityWithoutCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) +public class CsrfDisabledIntegrationTest extends CsrfAbstractIntegrationTest { + + @Test + public void givenNotAuth_whenAddFoo_thenUnauthorized() throws Exception { + mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo())).andExpect(status().isUnauthorized()); + } + + @Test + public void givenAuth_whenAddFoo_thenCreated() throws Exception { + mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isCreated()); + } + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfEnabledIntegrationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfEnabledIntegrationTest.java new file mode 100644 index 0000000000..fe6580bd05 --- /dev/null +++ b/spring-security-rest-full/src/test/java/org/baeldung/csrf/CsrfEnabledIntegrationTest.java @@ -0,0 +1,27 @@ +package org.baeldung.csrf; + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.baeldung.spring.PersistenceConfig; +import org.baeldung.spring.SecurityWithCsrfConfig; +import org.baeldung.spring.WebConfig; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; + +@ContextConfiguration(classes = { SecurityWithCsrfConfig.class, PersistenceConfig.class, WebConfig.class }) +public class CsrfEnabledIntegrationTest extends CsrfAbstractIntegrationTest { + + @Test + public void givenNoCsrf_whenAddFoo_thenForbidden() throws Exception { + mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser())).andExpect(status().isForbidden()); + } + + @Test + public void givenCsrf_whenAddFoo_thenCreated() throws Exception { + mvc.perform(post("/foos").contentType(MediaType.APPLICATION_JSON).content(createFoo()).with(testUser()).with(csrf())).andExpect(status().isCreated()); + } + +} diff --git a/spring-security-rest/pom.xml b/spring-security-rest/pom.xml index 2046b38810..265da0bbcd 100644 --- a/spring-security-rest/pom.xml +++ b/spring-security-rest/pom.xml @@ -92,6 +92,13 @@ ${jstl.version} runtime
+ + + javax.validation + validation-api + ${javax.validation.version} + + @@ -139,7 +146,33 @@ - + + org.springframework + spring-test + ${org.springframework.version} + test + + + + org.springframework.security + spring-security-test + ${org.springframework.security.version} + + + + + com.jayway.restassured + rest-assured + ${rest-assured.version} + test + + + commons-logging + commons-logging + + + + junit junit @@ -264,6 +297,7 @@ 5.2.2.Final 3.0.1 + 1.1.0.Final 1.2 2.2.2 2.2.2 @@ -276,6 +310,7 @@ 1.3 4.12 1.10.19 + 2.4.1 2.2.2 diff --git a/spring-security-rest/src/main/java/org/baeldung/persistence/model/Foo.java b/spring-security-rest/src/main/java/org/baeldung/persistence/model/Foo.java index 0124424f59..1941e2aa51 100644 --- a/spring-security-rest/src/main/java/org/baeldung/persistence/model/Foo.java +++ b/spring-security-rest/src/main/java/org/baeldung/persistence/model/Foo.java @@ -2,10 +2,13 @@ package org.baeldung.persistence.model; import java.io.Serializable; +import javax.validation.constraints.Size; + public class Foo implements Serializable { private long id; + @Size(min = 5, max = 14) private String name; public Foo() { diff --git a/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java index 5b88fefdb2..9abe604def 100644 --- a/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java +++ b/spring-security-rest/src/main/java/org/baeldung/spring/SecurityJavaConfig.java @@ -42,6 +42,7 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { .authenticationEntryPoint(restAuthenticationEntryPoint) .and() .authorizeRequests() + .antMatchers("/api/csrfAttacker*").permitAll() .antMatchers("/api/**").authenticated() .and() .formLogin() diff --git a/spring-security-rest/src/main/java/org/baeldung/spring/SwaggerConfig.java b/spring-security-rest/src/main/java/org/baeldung/spring/SwaggerConfig.java index 64f61055f2..00ccb36666 100644 --- a/spring-security-rest/src/main/java/org/baeldung/spring/SwaggerConfig.java +++ b/spring-security-rest/src/main/java/org/baeldung/spring/SwaggerConfig.java @@ -19,35 +19,13 @@ import static com.google.common.collect.Lists.newArrayList; public class SwaggerConfig { @Bean - public Docket api(){ - return new Docket(DocumentationType.SWAGGER_2) - .select() - .apis(RequestHandlerSelectors.basePackage("org.baeldung.web.controller")) - .paths(PathSelectors.ant("/foos/*")) - .build() - .apiInfo(apiInfo()) - .useDefaultResponseMessages(false) - .globalResponseMessage(RequestMethod.GET, - newArrayList(new ResponseMessageBuilder() - .code(500) - .message("500 message") - .responseModel(new ModelRef("Error")) - .build(), - new ResponseMessageBuilder() - .code(403) - .message("Forbidden!!!!!") - .build())); + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.basePackage("org.baeldung.web.controller")).paths(PathSelectors.ant("/foos/*")).build().apiInfo(apiInfo()).useDefaultResponseMessages(false) + .globalResponseMessage(RequestMethod.GET, newArrayList(new ResponseMessageBuilder().code(500).message("500 message").responseModel(new ModelRef("Error")).build(), new ResponseMessageBuilder().code(403).message("Forbidden!!!!!").build())); } private ApiInfo apiInfo() { - ApiInfo apiInfo = new ApiInfo( - "My REST API", - "Some custom description of API.", - "API TOS", - "Terms of service", - "myeaddress@company.com", - "License of API", - "API license URL"); + ApiInfo apiInfo = new ApiInfo("My REST API", "Some custom description of API.", "API TOS", "Terms of service", "myeaddress@company.com", "License of API", "API license URL"); return apiInfo; } } diff --git a/spring-security-rest/src/main/java/org/baeldung/spring/WebConfig.java b/spring-security-rest/src/main/java/org/baeldung/spring/WebConfig.java index 7e1e9cfcc3..064fd9afa9 100644 --- a/spring-security-rest/src/main/java/org/baeldung/spring/WebConfig.java +++ b/spring-security-rest/src/main/java/org/baeldung/spring/WebConfig.java @@ -1,10 +1,14 @@ package org.baeldung.spring; +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.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.view.InternalResourceViewResolver; @Configuration @ComponentScan("org.baeldung.web") @@ -16,12 +20,24 @@ public class WebConfig extends WebMvcConfigurerAdapter { } @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("swagger-ui.html") - .addResourceLocations("classpath:/META-INF/resources/"); + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); - registry.addResourceHandler("/webjars/**") - .addResourceLocations("classpath:/META-INF/resources/webjars/"); + registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); + } + + @Bean + public ViewResolver viewResolver() { + final InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); + viewResolver.setPrefix("/WEB-INF/view/"); + viewResolver.setSuffix(".jsp"); + return viewResolver; + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/csrfAttacker.html"); } } diff --git a/spring-security-rest/src/main/java/org/baeldung/web/ApiError.java b/spring-security-rest/src/main/java/org/baeldung/web/ApiError.java new file mode 100644 index 0000000000..e1c58da64a --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/web/ApiError.java @@ -0,0 +1,64 @@ +package org.baeldung.web; + +import java.util.Arrays; +import java.util.List; + +import org.springframework.http.HttpStatus; + +public class ApiError { + + private HttpStatus status; + private String message; + private List errors; + + // + + public ApiError() { + super(); + } + + public ApiError(final HttpStatus status, final String message, final List errors) { + super(); + this.status = status; + this.message = message; + this.errors = errors; + } + + public ApiError(final HttpStatus status, final String message, final String error) { + super(); + this.status = status; + this.message = message; + errors = Arrays.asList(error); + } + + // + + public HttpStatus getStatus() { + return status; + } + + public void setStatus(final HttpStatus status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(final String message) { + this.message = message; + } + + public List getErrors() { + return errors; + } + + public void setErrors(final List errors) { + this.errors = errors; + } + + public void setError(final String error) { + errors = Arrays.asList(error); + } + +} diff --git a/spring-security-rest/src/main/java/org/baeldung/web/CustomRestExceptionHandler.java b/spring-security-rest/src/main/java/org/baeldung/web/CustomRestExceptionHandler.java new file mode 100644 index 0000000000..71b1a4775e --- /dev/null +++ b/spring-security-rest/src/main/java/org/baeldung/web/CustomRestExceptionHandler.java @@ -0,0 +1,169 @@ +package org.baeldung.web; + +import java.util.ArrayList; +import java.util.List; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; + +import org.springframework.beans.TypeMismatchException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; +import org.springframework.web.HttpMediaTypeNotSupportedException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.MissingServletRequestParameterException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; +import org.springframework.web.multipart.support.MissingServletRequestPartException; +import org.springframework.web.servlet.NoHandlerFoundException; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@ControllerAdvice +public class CustomRestExceptionHandler extends ResponseEntityExceptionHandler { + + // 400 + + @Override + protected ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + logger.info(ex.getClass().getName()); + // + final List errors = new ArrayList(); + for (final FieldError error : ex.getBindingResult().getFieldErrors()) { + errors.add(error.getField() + ": " + error.getDefaultMessage()); + } + for (final ObjectError error : ex.getBindingResult().getGlobalErrors()) { + errors.add(error.getObjectName() + ": " + error.getDefaultMessage()); + } + final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors); + return handleExceptionInternal(ex, apiError, headers, apiError.getStatus(), request); + } + + @Override + protected ResponseEntity handleBindException(final BindException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + logger.info(ex.getClass().getName()); + // + final List errors = new ArrayList(); + for (final FieldError error : ex.getBindingResult().getFieldErrors()) { + errors.add(error.getField() + ": " + error.getDefaultMessage()); + } + for (final ObjectError error : ex.getBindingResult().getGlobalErrors()) { + errors.add(error.getObjectName() + ": " + error.getDefaultMessage()); + } + final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors); + return handleExceptionInternal(ex, apiError, headers, apiError.getStatus(), request); + } + + @Override + protected ResponseEntity handleTypeMismatch(final TypeMismatchException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + logger.info(ex.getClass().getName()); + // + final String error = ex.getValue() + " value for " + ex.getPropertyName() + " should be of type " + ex.getRequiredType(); + + final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error); + return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); + } + + @Override + protected ResponseEntity handleMissingServletRequestPart(final MissingServletRequestPartException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + logger.info(ex.getClass().getName()); + // + final String error = ex.getRequestPartName() + " part is missing"; + final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error); + return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); + } + + @Override + protected ResponseEntity handleMissingServletRequestParameter(final MissingServletRequestParameterException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + logger.info(ex.getClass().getName()); + // + final String error = ex.getParameterName() + " parameter is missing"; + final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error); + return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); + } + + // + + @ExceptionHandler({ MethodArgumentTypeMismatchException.class }) + public ResponseEntity handleMethodArgumentTypeMismatch(final MethodArgumentTypeMismatchException ex, final WebRequest request) { + logger.info(ex.getClass().getName()); + // + final String error = ex.getName() + " should be of type " + ex.getRequiredType().getName(); + + final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), error); + return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); + } + + @ExceptionHandler({ ConstraintViolationException.class }) + public ResponseEntity handleConstraintViolation(final ConstraintViolationException ex, final WebRequest request) { + logger.info(ex.getClass().getName()); + // + final List errors = new ArrayList(); + for (final ConstraintViolation violation : ex.getConstraintViolations()) { + errors.add(violation.getRootBeanClass().getName() + " " + violation.getPropertyPath() + ": " + violation.getMessage()); + } + + final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors); + return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); + } + + // 404 + + @Override + protected ResponseEntity handleNoHandlerFoundException(final NoHandlerFoundException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + logger.info(ex.getClass().getName()); + // + final String error = "No handler found for " + ex.getHttpMethod() + " " + ex.getRequestURL(); + + final ApiError apiError = new ApiError(HttpStatus.NOT_FOUND, ex.getLocalizedMessage(), error); + return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); + } + + // 405 + + @Override + protected ResponseEntity handleHttpRequestMethodNotSupported(final HttpRequestMethodNotSupportedException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + logger.info(ex.getClass().getName()); + // + final StringBuilder builder = new StringBuilder(); + builder.append(ex.getMethod()); + builder.append(" method is not supported for this request. Supported methods are "); + ex.getSupportedHttpMethods().forEach(t -> builder.append(t + " ")); + + final ApiError apiError = new ApiError(HttpStatus.METHOD_NOT_ALLOWED, ex.getLocalizedMessage(), builder.toString()); + return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); + } + + // 415 + + @Override + protected ResponseEntity handleHttpMediaTypeNotSupported(final HttpMediaTypeNotSupportedException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { + logger.info(ex.getClass().getName()); + // + final StringBuilder builder = new StringBuilder(); + builder.append(ex.getContentType()); + builder.append(" media type is not supported. Supported media types are "); + ex.getSupportedMediaTypes().forEach(t -> builder.append(t + " ")); + + final ApiError apiError = new ApiError(HttpStatus.UNSUPPORTED_MEDIA_TYPE, ex.getLocalizedMessage(), builder.substring(0, builder.length() - 2)); + return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); + } + + // 500 + + @ExceptionHandler({ Exception.class }) + public ResponseEntity handleAll(final Exception ex, final WebRequest request) { + logger.info(ex.getClass().getName()); + logger.error("error", ex); + // + final ApiError apiError = new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, ex.getLocalizedMessage(), "error occurred"); + return new ResponseEntity(apiError, new HttpHeaders(), apiError.getStatus()); + } + +} diff --git a/spring-security-rest/src/main/java/org/baeldung/web/controller/FooController.java b/spring-security-rest/src/main/java/org/baeldung/web/controller/FooController.java index cd0153540f..3b9e5d25c0 100644 --- a/spring-security-rest/src/main/java/org/baeldung/web/controller/FooController.java +++ b/spring-security-rest/src/main/java/org/baeldung/web/controller/FooController.java @@ -9,11 +9,14 @@ import javax.servlet.http.HttpServletResponse; import org.baeldung.persistence.model.Foo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.util.UriComponentsBuilder; import com.google.common.collect.Lists; @@ -47,4 +50,11 @@ public class FooController { return Lists.newArrayList(new Foo(randomAlphabetic(6))); } + // write - just for test + @RequestMapping(method = RequestMethod.POST) + @ResponseStatus(HttpStatus.CREATED) + @ResponseBody + public Foo create(@RequestBody final Foo foo) { + return foo; + } } diff --git a/spring-security-rest/src/main/webapp/WEB-INF/view/csrfAttacker.jsp b/spring-security-rest/src/main/webapp/WEB-INF/view/csrfAttacker.jsp new file mode 100644 index 0000000000..2e87d2d07e --- /dev/null +++ b/spring-security-rest/src/main/webapp/WEB-INF/view/csrfAttacker.jsp @@ -0,0 +1,16 @@ + + + + +

CSRF Attacker

+ Show Kittens Pictures + + + +
+ + + +
+ + \ No newline at end of file diff --git a/spring-security-rest/src/main/webapp/WEB-INF/web.xml b/spring-security-rest/src/main/webapp/WEB-INF/web.xml index 54f95d6227..3af8709dab 100644 --- a/spring-security-rest/src/main/webapp/WEB-INF/web.xml +++ b/spring-security-rest/src/main/webapp/WEB-INF/web.xml @@ -26,8 +26,11 @@ api - org.springframework.web.servlet.DispatcherServlet - 1 + org.springframework.web.servlet.DispatcherServlet + + throwExceptionIfNoHandlerFound + true + api diff --git a/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java b/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java new file mode 100644 index 0000000000..6e03300483 --- /dev/null +++ b/spring-security-rest/src/test/java/org/baeldung/web/FooLiveTest.java @@ -0,0 +1,70 @@ +package org.baeldung.web; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.http.HttpStatus; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.jayway.restassured.RestAssured; +import com.jayway.restassured.authentication.FormAuthConfig; +import com.jayway.restassured.response.Response; +import com.jayway.restassured.specification.RequestSpecification; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) +public class FooLiveTest { + private static final String URL_PREFIX = "http://localhost:8080/spring-security-rest"; + private FormAuthConfig formConfig = new FormAuthConfig(URL_PREFIX + "/login", "username", "password"); + + private RequestSpecification givenAuth() { + return RestAssured.given().auth().form("user", "userPass", formConfig); + } + + @Test + public void whenMethodArgumentMismatch_thenBadRequest() { + final Response response = givenAuth().get(URL_PREFIX + "/api/foos/ccc"); + final ApiError error = response.as(ApiError.class); + assertEquals(HttpStatus.BAD_REQUEST, error.getStatus()); + assertEquals(1, error.getErrors().size()); + assertTrue(error.getErrors().get(0).contains("should be of type")); + } + + @Test + public void whenNoHandlerForHttpRequest_thenNotFound() { + final Response response = givenAuth().delete(URL_PREFIX + "/api/xx"); + final ApiError error = response.as(ApiError.class); + assertEquals(HttpStatus.NOT_FOUND, error.getStatus()); + assertEquals(1, error.getErrors().size()); + assertTrue(error.getErrors().get(0).contains("No handler found")); + System.out.println(response.asString()); + + } + + @Test + public void whenHttpRequestMethodNotSupported_thenMethodNotAllowed() { + final Response response = givenAuth().delete(URL_PREFIX + "/api/foos/1"); + final ApiError error = response.as(ApiError.class); + assertEquals(HttpStatus.METHOD_NOT_ALLOWED, error.getStatus()); + assertEquals(1, error.getErrors().size()); + assertTrue(error.getErrors().get(0).contains("Supported methods are")); + System.out.println(response.asString()); + + } + + @Test + public void whenSendInvalidHttpMediaType_thenUnsupportedMediaType() { + final Response response = givenAuth().body("").post(URL_PREFIX + "/api/foos"); + final ApiError error = response.as(ApiError.class); + assertEquals(HttpStatus.UNSUPPORTED_MEDIA_TYPE, error.getStatus()); + assertEquals(1, error.getErrors().size()); + assertTrue(error.getErrors().get(0).contains("media type is not supported")); + System.out.println(response.asString()); + + } + +} diff --git a/spring-security-rest/src/test/java/org/baeldung/web/TestConfig.java b/spring-security-rest/src/test/java/org/baeldung/web/TestConfig.java new file mode 100644 index 0000000000..8b55841508 --- /dev/null +++ b/spring-security-rest/src/test/java/org/baeldung/web/TestConfig.java @@ -0,0 +1,10 @@ +package org.baeldung.web; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan({ "org.baeldung.web" }) +public class TestConfig { + +} \ No newline at end of file diff --git a/spring-zuul/.project b/spring-zuul/.project new file mode 100644 index 0000000000..cc40816960 --- /dev/null +++ b/spring-zuul/.project @@ -0,0 +1,17 @@ + + + spring-zuul + + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + + diff --git a/spring-zuul/pom.xml b/spring-zuul/pom.xml new file mode 100644 index 0000000000..6ad1d0be34 --- /dev/null +++ b/spring-zuul/pom.xml @@ -0,0 +1,101 @@ + + 4.0.0 + org.baeldung + spring-zuul + 1.0.0-SNAPSHOT + + spring-zuul + pom + + + org.springframework.boot + spring-boot-starter-parent + 1.3.1.RELEASE + + + + spring-zuul-foos-resource + spring-zuul-ui + + + + spring-zuul + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + false + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + true + + **/*IntegrationTest.java + **/*LiveTest.java + + + + + + + + + + + + + + + 4.2.2.RELEASE + 4.0.3.RELEASE + + + + 2.5.1 + + + 1.7.12 + 1.1.3 + + + 18.0 + 3.3.2 + + + 1.3 + 4.11 + 1.10.19 + + 4.4 + 4.4 + + 2.4.0 + + + 3.3 + 2.6 + 2.19 + 1.4.16 + + + + \ No newline at end of file diff --git a/spring-zuul/spring-zuul-foos-resource/.classpath b/spring-zuul/spring-zuul-foos-resource/.classpath new file mode 100644 index 0000000000..0cad5db2d0 --- /dev/null +++ b/spring-zuul/spring-zuul-foos-resource/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-zuul/spring-zuul-foos-resource/.project b/spring-zuul/spring-zuul-foos-resource/.project new file mode 100644 index 0000000000..8d04c873fb --- /dev/null +++ b/spring-zuul/spring-zuul-foos-resource/.project @@ -0,0 +1,48 @@ + + + spring-zuul-foos-resource + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/spring-zuul/spring-zuul-foos-resource/pom.xml b/spring-zuul/spring-zuul-foos-resource/pom.xml new file mode 100644 index 0000000000..6d5e0e52cf --- /dev/null +++ b/spring-zuul/spring-zuul-foos-resource/pom.xml @@ -0,0 +1,38 @@ + + 4.0.0 + spring-zuul-foos-resource + spring-zuul-foos-resource + war + + + org.baeldung + spring-zuul + 1.0.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + + + spring-zuul-foos-resource + + + src/main/resources + true + + + + + \ No newline at end of file diff --git a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java new file mode 100644 index 0000000000..1e35eff551 --- /dev/null +++ b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerApplication.java @@ -0,0 +1,14 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.web.SpringBootServletInitializer; + +@SpringBootApplication +public class ResourceServerApplication extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(ResourceServerApplication.class, args); + } + +} \ No newline at end of file diff --git a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java new file mode 100644 index 0000000000..c040c8ac42 --- /dev/null +++ b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/config/ResourceServerWebConfig.java @@ -0,0 +1,13 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@EnableWebMvc +@ComponentScan({ "org.baeldung.web.controller" }) +public class ResourceServerWebConfig extends WebMvcConfigurerAdapter { + +} diff --git a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/web/controller/FooController.java b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/web/controller/FooController.java new file mode 100644 index 0000000000..486f858ab5 --- /dev/null +++ b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/web/controller/FooController.java @@ -0,0 +1,35 @@ +package org.baeldung.web.controller; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.baeldung.web.dto.Foo; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class FooController { + + public FooController() { + super(); + } + + // API - read + @RequestMapping(method = RequestMethod.GET, value = "/foos/{id}") + @ResponseBody + public Foo findById(@PathVariable final long id, HttpServletRequest req, HttpServletResponse res) { + // System.out.println(req.getHeaderNames()); + // System.out.println("------" + req.getHeader("Test")); + if (req.getHeader("Test") != null) { + res.addHeader("Test", req.getHeader("Test")); + } + return new Foo(Long.parseLong(randomNumeric(2)), randomAlphabetic(4)); + } + +} diff --git a/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/web/dto/Foo.java b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/web/dto/Foo.java new file mode 100644 index 0000000000..9d26618e7f --- /dev/null +++ b/spring-zuul/spring-zuul-foos-resource/src/main/java/org/baeldung/web/dto/Foo.java @@ -0,0 +1,36 @@ +package org.baeldung.web.dto; + +public class Foo { + private long id; + private String name; + + public Foo() { + super(); + } + + public Foo(final long id, final String name) { + super(); + + this.id = id; + this.name = name; + } + + // + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + +} \ No newline at end of file diff --git a/spring-zuul/spring-zuul-foos-resource/src/main/resources/application.properties b/spring-zuul/spring-zuul-foos-resource/src/main/resources/application.properties new file mode 100644 index 0000000000..94c0984ac3 --- /dev/null +++ b/spring-zuul/spring-zuul-foos-resource/src/main/resources/application.properties @@ -0,0 +1,2 @@ +server.contextPath=/spring-zuul-foos-resource +server.port=8081 \ No newline at end of file diff --git a/spring-zuul/spring-zuul-ui/.classpath b/spring-zuul/spring-zuul-ui/.classpath new file mode 100644 index 0000000000..5c3ac53820 --- /dev/null +++ b/spring-zuul/spring-zuul-ui/.classpath @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-zuul/spring-zuul-ui/.project b/spring-zuul/spring-zuul-ui/.project new file mode 100644 index 0000000000..ec0f2cde81 --- /dev/null +++ b/spring-zuul/spring-zuul-ui/.project @@ -0,0 +1,48 @@ + + + spring-zuul-ui + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/spring-zuul/spring-zuul-ui/pom.xml b/spring-zuul/spring-zuul-ui/pom.xml new file mode 100644 index 0000000000..65a025f849 --- /dev/null +++ b/spring-zuul/spring-zuul-ui/pom.xml @@ -0,0 +1,91 @@ + + 4.0.0 + spring-zuul-ui + + spring-zuul-ui + war + + + org.baeldung + spring-zuul + 1.0.0-SNAPSHOT + + + + + + + org.springframework.cloud + spring-cloud-starter-zuul + 1.0.4.RELEASE + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.springframework + spring-test + test + + + + junit + junit + test + + + + org.hamcrest + hamcrest-core + test + + + org.hamcrest + hamcrest-library + test + + + + org.mockito + mockito-core + test + + + + com.jayway.restassured + rest-assured + ${rest-assured.version} + test + + + commons-logging + commons-logging + + + + + + + spring-zuul-ui + + + src/main/resources + true + + + + \ No newline at end of file diff --git a/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/CustomZuulFilter.java b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/CustomZuulFilter.java new file mode 100644 index 0000000000..826ac64e9f --- /dev/null +++ b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/CustomZuulFilter.java @@ -0,0 +1,33 @@ +package org.baeldung.config; + +import org.springframework.stereotype.Component; + +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; + +@Component +public class CustomZuulFilter extends ZuulFilter { + + @Override + public Object run() { + final RequestContext ctx = RequestContext.getCurrentContext(); + ctx.addZuulRequestHeader("Test", "TestSample"); + return null; + } + + @Override + public boolean shouldFilter() { + return true; + } + + @Override + public int filterOrder() { + return 1110; + } + + @Override + public String filterType() { + return "pre"; + } + +} diff --git a/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiApplication.java b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiApplication.java new file mode 100644 index 0000000000..625e5439ee --- /dev/null +++ b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiApplication.java @@ -0,0 +1,14 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.zuul.EnableZuulProxy; + +@EnableZuulProxy +@SpringBootApplication +public class UiApplication { + + public static void main(String[] args) { + SpringApplication.run(UiApplication.class, args); + } +} \ No newline at end of file diff --git a/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiWebConfig.java b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiWebConfig.java new file mode 100644 index 0000000000..0732182354 --- /dev/null +++ b/spring-zuul/spring-zuul-ui/src/main/java/org/baeldung/config/UiWebConfig.java @@ -0,0 +1,39 @@ +package org.baeldung.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@Configuration +@EnableWebMvc +public class UiWebConfig extends WebMvcConfigurerAdapter { + + @Bean + public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Override + public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) { + configurer.enable(); + } + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/").setViewName("forward:/index"); + registry.addViewController("/index"); + registry.addViewController("/login"); + } + + @Override + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } + +} \ No newline at end of file diff --git a/spring-zuul/spring-zuul-ui/src/main/resources/application.yml b/spring-zuul/spring-zuul-ui/src/main/resources/application.yml new file mode 100644 index 0000000000..855020a40e --- /dev/null +++ b/spring-zuul/spring-zuul-ui/src/main/resources/application.yml @@ -0,0 +1,5 @@ +zuul: + routes: + foos: + path: /foos/** + url: http://localhost:8081/spring-zuul-foos-resource/foos diff --git a/spring-zuul/spring-zuul-ui/src/main/resources/templates/index.html b/spring-zuul/spring-zuul-ui/src/main/resources/templates/index.html new file mode 100755 index 0000000000..d279f9eaf9 --- /dev/null +++ b/spring-zuul/spring-zuul-ui/src/main/resources/templates/index.html @@ -0,0 +1,58 @@ + + + + +Spring Zuul + + + + +
+ + + + + + + +
+
+

Foo Details

+
+ + {{foo.id}} +
+ +
+ + {{foo.name}} +
+ +
+ New Foo +
+ +
+ + \ No newline at end of file diff --git a/spring-zuul/spring-zuul-ui/src/main/webapp/resources/angular-utf8-base64.min.js b/spring-zuul/spring-zuul-ui/src/main/webapp/resources/angular-utf8-base64.min.js new file mode 100644 index 0000000000..24af57d020 --- /dev/null +++ b/spring-zuul/spring-zuul-ui/src/main/webapp/resources/angular-utf8-base64.min.js @@ -0,0 +1 @@ +"use strict";angular.module("ab-base64",[]).constant("base64",function(){var a={alphabet:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",lookup:null,ie:/MSIE /.test(navigator.userAgent),ieo:/MSIE [67]/.test(navigator.userAgent),encode:function(b){var c,d,e,f,g=a.toUtf8(b),h=-1,i=g.length,j=[,,,];if(a.ie){for(c=[];++h>2,j[1]=(3&d)<<4|e>>4,isNaN(e)?j[2]=j[3]=64:(f=g[++h],j[2]=(15&e)<<2|f>>6,j[3]=isNaN(f)?64:63&f),c.push(a.alphabet.charAt(j[0]),a.alphabet.charAt(j[1]),a.alphabet.charAt(j[2]),a.alphabet.charAt(j[3]));return c.join("")}for(c="";++h>2,j[1]=(3&d)<<4|e>>4,isNaN(e)?j[2]=j[3]=64:(f=g[++h],j[2]=(15&e)<<2|f>>6,j[3]=isNaN(f)?64:63&f),c+=a.alphabet[j[0]]+a.alphabet[j[1]]+a.alphabet[j[2]]+a.alphabet[j[3]];return c},decode:function(b){if(b=b.replace(/\s/g,""),b.length%4)throw new Error("InvalidLengthError: decode failed: The string to be decoded is not the correct length for a base64 encoded string.");if(/[^A-Za-z0-9+\/=\s]/g.test(b))throw new Error("InvalidCharacterError: decode failed: The string contains characters invalid in a base64 encoded string.");var c,d=a.fromUtf8(b),e=0,f=d.length;if(a.ieo){for(c=[];f>e;)c.push(d[e]<128?String.fromCharCode(d[e++]):d[e]>191&&d[e]<224?String.fromCharCode((31&d[e++])<<6|63&d[e++]):String.fromCharCode((15&d[e++])<<12|(63&d[e++])<<6|63&d[e++]));return c.join("")}for(c="";f>e;)c+=String.fromCharCode(d[e]<128?d[e++]:d[e]>191&&d[e]<224?(31&d[e++])<<6|63&d[e++]:(15&d[e++])<<12|(63&d[e++])<<6|63&d[e++]);return c},toUtf8:function(a){var b,c=-1,d=a.length,e=[];if(/^[\x00-\x7f]*$/.test(a))for(;++cb?e.push(b):2048>b?e.push(b>>6|192,63&b|128):e.push(b>>12|224,b>>6&63|128,63&b|128);return e},fromUtf8:function(b){var c,d=-1,e=[],f=[,,,];if(!a.lookup){for(c=a.alphabet.length,a.lookup={};++d>4),f[2]=a.lookup[b.charAt(++d)],64!==f[2])&&(e.push((15&f[1])<<4|f[2]>>2),f[3]=a.lookup[b.charAt(++d)],64!==f[3]);)e.push((3&f[2])<<6|f[3]);return e}},b={decode:function(b){b=b.replace(/-/g,"+").replace(/_/g,"/");var c=b.length%4;if(c){if(1===c)throw new Error("InvalidLengthError: Input base64url string is the wrong length to determine padding");b+=new Array(5-c).join("=")}return a.decode(b)},encode:function(b){var c=a.encode(b);return c.replace(/\+/g,"-").replace(/\//g,"_").split("=",1)[0]}};return{decode:a.decode,encode:a.encode,urldecode:b.decode,urlencode:b.encode}}()); \ No newline at end of file diff --git a/spring-zuul/spring-zuul-ui/src/test/java/org/baeldung/web/LiveTest.java b/spring-zuul/spring-zuul-ui/src/test/java/org/baeldung/web/LiveTest.java new file mode 100644 index 0000000000..7ced527778 --- /dev/null +++ b/spring-zuul/spring-zuul-ui/src/test/java/org/baeldung/web/LiveTest.java @@ -0,0 +1,24 @@ +package org.baeldung.web; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.jayway.restassured.RestAssured; +import com.jayway.restassured.response.Response; + +public class LiveTest { + + @Test + public void whenSendRequestToFooResource_thenOK() { + final Response response = RestAssured.get("http://localhost:8080/foos/1"); + assertEquals(200, response.getStatusCode()); + } + + @Test + public void whenSendRequest_thenHeaderAdded() { + final Response response = RestAssured.get("http://localhost:8080/foos/1"); + assertEquals(200, response.getStatusCode()); + assertEquals("TestSample", response.getHeader("Test")); + } +} diff --git a/spring-zuul/spring-zuul-ui/src/test/resources/.gitignore b/spring-zuul/spring-zuul-ui/src/test/resources/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-zuul/spring-zuul-ui/src/test/resources/.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-zuul/spring-zuul-ui/src/test/resources/persistence-mysql.properties b/spring-zuul/spring-zuul-ui/src/test/resources/persistence-mysql.properties new file mode 100644 index 0000000000..8263b0d9ac --- /dev/null +++ b/spring-zuul/spring-zuul-ui/src/test/resources/persistence-mysql.properties @@ -0,0 +1,10 @@ +# jdbc.X +jdbc.driverClassName=com.mysql.jdbc.Driver +jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate4_01?createDatabaseIfNotExist=true +jdbc.user=tutorialuser +jdbc.pass=tutorialmy5ql + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.MySQL5Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop