diff --git a/README.md b/README.md index 3e88f0c017..da46989455 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ The "REST with Spring" Classes ============================== -This is what I'm working on:
-**[>> THE REST WITH SPRING CLASSES](http://www.baeldung.com/rest-with-spring-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=25off)** +After 5 months of work, here's the Master Class:
+**[>> THE REST WITH SPRING MASTER CLASS](http://www.baeldung.com/rest-with-spring-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=rws#master-class)** Spring Tutorials diff --git a/RestEasy Example/pom.xml b/RestEasy Example/pom.xml new file mode 100644 index 0000000000..ec9e87b0d1 --- /dev/null +++ b/RestEasy Example/pom.xml @@ -0,0 +1,77 @@ + + + 4.0.0 + + com.baeldung + resteasy-tutorial + 1.0 + war + + + 3.0.14.Final + + + + RestEasyTutorial + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + + + + org.jboss.resteasy + resteasy-servlet-initializer + ${resteasy.version} + + + + + org.jboss.resteasy + resteasy-client + ${resteasy.version} + + + + + + org.jboss.resteasy + resteasy-jaxb-provider + ${resteasy.version} + + + + org.jboss.resteasy + resteasy-jackson-provider + ${resteasy.version} + + + + + + junit + junit + 4.4 + + + + commons-io + commons-io + 2.4 + + + + + + \ No newline at end of file diff --git a/RestEasy Example/src/main/java/com/baeldung/client/ServicesInterface.java b/RestEasy Example/src/main/java/com/baeldung/client/ServicesInterface.java new file mode 100644 index 0000000000..3d03c16faf --- /dev/null +++ b/RestEasy Example/src/main/java/com/baeldung/client/ServicesInterface.java @@ -0,0 +1,36 @@ +package com.baeldung.client; + +import com.baeldung.model.Movie; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.List; + +@Path("/movies") +public interface ServicesInterface { + + @GET + @Path("/getinfo") + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + Movie movieByImdbId(@QueryParam("imdbId") String imdbId); + + @GET + @Path("/listmovies") + @Produces({ "application/json" }) + List listMovies(); + + @POST + @Path("/addmovie") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + Response addMovie(Movie movie); + + @PUT + @Path("/updatemovie") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + Response updateMovie(Movie movie); + + @DELETE + @Path("/deletemovie") + Response deleteMovie(@QueryParam("imdbId") String imdbID); + +} diff --git a/RestEasy Example/src/main/java/com/baeldung/model/Movie.java b/RestEasy Example/src/main/java/com/baeldung/model/Movie.java new file mode 100644 index 0000000000..408f2144fb --- /dev/null +++ b/RestEasy Example/src/main/java/com/baeldung/model/Movie.java @@ -0,0 +1,66 @@ +package com.baeldung.model; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "movie", propOrder = { "imdbId", "title" }) +public class Movie { + + protected String imdbId; + protected String title; + + public Movie(String imdbId, String title) { + this.imdbId = imdbId; + this.title = title; + } + + public Movie() {} + + public String getImdbId() { + return imdbId; + } + + public void setImdbId(String imdbId) { + this.imdbId = imdbId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Movie movie = (Movie) o; + + if (imdbId != null ? !imdbId.equals(movie.imdbId) : movie.imdbId != null) + return false; + return title != null ? title.equals(movie.title) : movie.title == null; + + } + + @Override + public int hashCode() { + int result = imdbId != null ? imdbId.hashCode() : 0; + result = 31 * result + (title != null ? title.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Movie{" + + "imdbId='" + imdbId + '\'' + + ", title='" + title + '\'' + + '}'; + } +} diff --git a/RestEasy Example/src/main/java/com/baeldung/server/MovieCrudService.java b/RestEasy Example/src/main/java/com/baeldung/server/MovieCrudService.java new file mode 100644 index 0000000000..b7f3215f3f --- /dev/null +++ b/RestEasy Example/src/main/java/com/baeldung/server/MovieCrudService.java @@ -0,0 +1,83 @@ +package com.baeldung.server; + +import com.baeldung.model.Movie; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Path("/movies") +public class MovieCrudService { + + private Map inventory = new HashMap(); + + @GET + @Path("/getinfo") + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public Movie movieByImdbId(@QueryParam("imdbId") String imdbId) { + + System.out.println("*** Calling getinfo for a given ImdbID***"); + + if (inventory.containsKey(imdbId)) { + return inventory.get(imdbId); + } else + return null; + } + + @POST + @Path("/addmovie") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public Response addMovie(Movie movie) { + + System.out.println("*** Calling addMovie ***"); + + if (null != inventory.get(movie.getImdbId())) { + return Response.status(Response.Status.NOT_MODIFIED).entity("Movie is Already in the database.").build(); + } + + inventory.put(movie.getImdbId(), movie); + return Response.status(Response.Status.CREATED).build(); + } + + @PUT + @Path("/updatemovie") + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + public Response updateMovie(Movie movie) { + + System.out.println("*** Calling updateMovie ***"); + + if (null == inventory.get(movie.getImdbId())) { + return Response.status(Response.Status.NOT_MODIFIED).entity("Movie is not in the database.\nUnable to Update").build(); + } + + inventory.put(movie.getImdbId(), movie); + return Response.status(Response.Status.OK).build(); + } + + @DELETE + @Path("/deletemovie") + public Response deleteMovie(@QueryParam("imdbId") String imdbId) { + + System.out.println("*** Calling deleteMovie ***"); + + if (null == inventory.get(imdbId)) { + return Response.status(Response.Status.NOT_FOUND).entity("Movie is not in the database.\nUnable to Delete").build(); + } + + inventory.remove(imdbId); + return Response.status(Response.Status.OK).build(); + } + + @GET + @Path("/listmovies") + @Produces({ "application/json" }) + public List listMovies() { + + return inventory.values().stream().collect(Collectors.toCollection(ArrayList::new)); + } + +} diff --git a/RestEasy Example/src/main/java/com/baeldung/server/RestEasyServices.java b/RestEasy Example/src/main/java/com/baeldung/server/RestEasyServices.java new file mode 100644 index 0000000000..7726e49f38 --- /dev/null +++ b/RestEasy Example/src/main/java/com/baeldung/server/RestEasyServices.java @@ -0,0 +1,32 @@ +package com.baeldung.server; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +@ApplicationPath("/rest") +public class RestEasyServices extends Application { + + private Set singletons = new HashSet(); + + public RestEasyServices() { + singletons.add(new MovieCrudService()); + } + + @Override + public Set getSingletons() { + return singletons; + } + + @Override + public Set> getClasses() { + return super.getClasses(); + } + + @Override + public Map getProperties() { + return super.getProperties(); + } +} diff --git a/RestEasy Example/src/main/webapp/WEB-INF/classes/logback.xml b/RestEasy Example/src/main/webapp/WEB-INF/classes/logback.xml new file mode 100644 index 0000000000..d94e9f71ab --- /dev/null +++ b/RestEasy Example/src/main/webapp/WEB-INF/classes/logback.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/RestEasy Example/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/RestEasy Example/src/main/webapp/WEB-INF/jboss-deployment-structure.xml new file mode 100644 index 0000000000..cb258374a1 --- /dev/null +++ b/RestEasy Example/src/main/webapp/WEB-INF/jboss-deployment-structure.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/RestEasy Example/src/main/webapp/WEB-INF/jboss-web.xml b/RestEasy Example/src/main/webapp/WEB-INF/jboss-web.xml new file mode 100644 index 0000000000..694bb71332 --- /dev/null +++ b/RestEasy Example/src/main/webapp/WEB-INF/jboss-web.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/RestEasy Example/src/main/webapp/WEB-INF/web.xml b/RestEasy Example/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..d5f00293f4 --- /dev/null +++ b/RestEasy Example/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,13 @@ + + + + RestEasy Example + + + resteasy.servlet.mapping.prefix + /rest + + + \ No newline at end of file diff --git a/apache-fop/pom.xml b/apache-fop/pom.xml index 13fc2257cf..95505f9374 100644 --- a/apache-fop/pom.xml +++ b/apache-fop/pom.xml @@ -37,7 +37,7 @@ junit - junit-dep + junit ${junit.version} test @@ -151,7 +151,7 @@ 5.1.34 - 2.4.4 + 2.5.5 1.7.9 @@ -166,7 +166,7 @@ 1.3 - 4.11 + 4.12 1.10.19 4.4 diff --git a/core-java-8/.settings/org.eclipse.jdt.core.prefs b/core-java-8/.settings/org.eclipse.jdt.core.prefs index c57289fc09..c38ccc1294 100644 --- a/core-java-8/.settings/org.eclipse.jdt.core.prefs +++ b/core-java-8/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,5 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault @@ -26,7 +27,7 @@ org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=error +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning @@ -35,7 +36,7 @@ org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore -org.eclipse.jdt.core.compiler.problem.localVariableHiding=error +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore @@ -48,6 +49,7 @@ org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignor org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error org.eclipse.jdt.core.compiler.problem.nullReference=warning org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error @@ -68,6 +70,7 @@ org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore org.eclipse.jdt.core.compiler.problem.typeParameterHiding=error org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled @@ -82,6 +85,7 @@ org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedImport=warning org.eclipse.jdt.core.compiler.problem.unusedLabel=warning org.eclipse.jdt.core.compiler.problem.unusedLocal=warning @@ -91,6 +95,7 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference= org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.source=1.8 diff --git a/core-java-8/README.md b/core-java-8/README.md index 9bb6bb811c..8bef3a1be0 100644 --- a/core-java-8/README.md +++ b/core-java-8/README.md @@ -3,4 +3,8 @@ ## Core Java 8 Cookbooks and Examples ### Relevant Articles: -// - [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda) +// - [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda) +- [Java – Directory Size](http://www.baeldung.com/java-folder-size) +- [Java – Try with Resources](http://www.baeldung.com/java-try-with-resources) +- [Lambda Expressions and Functional Interfaces: Tips and Best Practices](http://www.baeldung.com/java-8-lambda-expressions-tips) +- [The Double Colon Operator in Java 8](http://www.baeldung.com/java-8-double-colon-operator) diff --git a/core-java-8/pom.xml b/core-java-8/pom.xml index 9db2562fb4..07d3bcd146 100644 --- a/core-java-8/pom.xml +++ b/core-java-8/pom.xml @@ -98,14 +98,14 @@ - 1.7.12 + 1.7.13 1.0.13 5.1.3.Final - 18.0 + 19.0 3.4 diff --git a/core-java-8/src/main/java/com/baeldung/Adder.java b/core-java-8/src/main/java/com/baeldung/Adder.java new file mode 100644 index 0000000000..e3e100f121 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/Adder.java @@ -0,0 +1,12 @@ +package com.baeldung; + +import java.util.function.Consumer; +import java.util.function.Function; + +public interface Adder { + + String addWithFunction(Function f); + + void addWithConsumer(Consumer f); + +} diff --git a/core-java-8/src/main/java/com/baeldung/AdderImpl.java b/core-java-8/src/main/java/com/baeldung/AdderImpl.java new file mode 100644 index 0000000000..f67cdc26b3 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/AdderImpl.java @@ -0,0 +1,17 @@ +package com.baeldung; + +import java.util.function.Consumer; +import java.util.function.Function; + +public class AdderImpl implements Adder { + + @Override + public String addWithFunction(final Function f) { + return f.apply("Something "); + } + + @Override + public void addWithConsumer(final Consumer f) { + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/Bar.java b/core-java-8/src/main/java/com/baeldung/Bar.java new file mode 100644 index 0000000000..f9b6f2773e --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/Bar.java @@ -0,0 +1,12 @@ +package com.baeldung; + +@FunctionalInterface +public interface Bar { + + String method(String string); + + default String defaultMethod() { + return "String from Bar"; + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/Baz.java b/core-java-8/src/main/java/com/baeldung/Baz.java new file mode 100644 index 0000000000..6d03f74198 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/Baz.java @@ -0,0 +1,11 @@ +package com.baeldung; + +@FunctionalInterface +public interface Baz { + + String method(String string); + + default String defaultMethod() { + return "String from Baz"; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/Foo.java b/core-java-8/src/main/java/com/baeldung/Foo.java new file mode 100644 index 0000000000..90ebdfeed3 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/Foo.java @@ -0,0 +1,10 @@ +package com.baeldung; + +@FunctionalInterface +public interface Foo { + + String method(String string); + + default void defaultMethod() { + } +} diff --git a/core-java-8/src/main/java/com/baeldung/FooExtended.java b/core-java-8/src/main/java/com/baeldung/FooExtended.java new file mode 100644 index 0000000000..c8ed0c35dd --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/FooExtended.java @@ -0,0 +1,11 @@ +package com.baeldung; + +@FunctionalInterface +public interface FooExtended extends Baz, Bar { + + @Override + default String defaultMethod() { + return Bar.super.defaultMethod(); + } + +} diff --git a/core-java-8/src/main/java/com/baeldung/UseFoo.java b/core-java-8/src/main/java/com/baeldung/UseFoo.java new file mode 100644 index 0000000000..a91404ebaf --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/UseFoo.java @@ -0,0 +1,37 @@ +package com.baeldung; + +import java.util.function.Function; + +public class UseFoo { + + private String value = "Enclosing scope value"; + + public String add(final String string, final Foo foo) { + return foo.method(string); + } + + public String addWithStandardFI(final String string, final Function fn) { + return fn.apply(string); + } + + public String scopeExperiment() { + final Foo fooIC = new Foo() { + String value = "Inner class value"; + + @Override + public String method(final String string) { + return value; + } + }; + final String resultIC = fooIC.method(""); + + final Foo fooLambda = parameter -> { + final String value = "Lambda value"; + return this.value; + }; + final String resultLambda = fooLambda.method(""); + + return "Results: resultIC = " + resultIC + ", resultLambda = " + resultLambda; + } + +} 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/org/baeldung/java8/Java8CollectionCleanupUnitTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java similarity index 80% rename from core-java-8/src/test/java/org/baeldung/java8/Java8CollectionCleanupUnitTest.java rename to core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java index acca829b78..9c248ad8ce 100644 --- a/core-java-8/src/test/java/org/baeldung/java8/Java8CollectionCleanupUnitTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8CollectionCleanupUnitTest.java @@ -1,4 +1,4 @@ -package org.baeldung.java8; +package com.baeldung.java8; import static org.hamcrest.Matchers.hasSize; import static org.junit.Assert.assertThat; @@ -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/core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasTest.java new file mode 100644 index 0000000000..94448fcc83 --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasTest.java @@ -0,0 +1,95 @@ +package com.baeldung.java8; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import java.util.function.Function; + +import org.junit.Before; +import org.junit.Test; + +import com.baeldung.Foo; +import com.baeldung.FooExtended; +import com.baeldung.UseFoo; + +public class Java8FunctionalInteracesLambdasTest { + + private UseFoo useFoo; + + @Before + public void init() { + useFoo = new UseFoo(); + } + + @Test + public void functionalInterfaceInstantiation_whenReturnDefiniteString_thenCorrect() { + final Foo foo = parameter -> parameter + "from lambda"; + final String result = useFoo.add("Message ", foo); + + assertEquals("Message from lambda", result); + } + + @Test + public void standardFIParameter_whenReturnDefiniteString_thenCorrect() { + final Function fn = parameter -> parameter + "from lambda"; + final String result = useFoo.addWithStandardFI("Message ", fn); + + assertEquals("Message from lambda", result); + } + + @Test + public void defaultMethodFromExtendedInterface_whenReturnDefiniteString_thenCorrect() { + final FooExtended fooExtended = string -> string; + final String result = fooExtended.defaultMethod(); + + assertEquals("String from Bar", result); + } + + @Test + public void lambdaAndInnerClassInstantiation_whenReturnSameString_thenCorrect() { + final Foo foo = parameter -> parameter + "from Foo"; + + final Foo fooByIC = new Foo() { + @Override + public String method(final String string) { + return string + "from Foo"; + } + }; + + assertEquals(foo.method("Something "), fooByIC.method("Something ")); + } + + @Test + public void accessVariablesFromDifferentScopes_whenReturnPredefinedString_thenCorrect() { + assertEquals("Results: resultIC = Inner class value, resultLambda = Enclosing scope value", useFoo.scopeExperiment()); + } + + @Test + public void shorteningLambdas_whenReturnEqualsResults_thenCorrect() { + final Foo foo = parameter -> buildString(parameter); + + final Foo fooHuge = parameter -> { + final String result = "Something " + parameter; + // many lines of code + return result; + }; + + assertEquals(foo.method("Something"), fooHuge.method("Something")); + } + + private String buildString(final String parameter) { + final String result = "Something " + parameter; + // many lines of code + return result; + } + + @Test + public void mutatingOfEffectivelyFinalVariable_whenNotEquals_thenCorrect() { + final int[] total = new int[1]; + final Runnable r = () -> total[0]++; + r.run(); + + assertNotEquals(0, total[0]); + } + +} diff --git a/core-java-8/src/test/java/org/baeldung/java8/Java8SortUnitTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java similarity index 98% rename from core-java-8/src/test/java/org/baeldung/java8/Java8SortUnitTest.java rename to core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java index 8ed7828de0..2ba9e417d6 100644 --- a/core-java-8/src/test/java/org/baeldung/java8/Java8SortUnitTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java @@ -1,4 +1,4 @@ -package org.baeldung.java8; +package com.baeldung.java8; import static org.hamcrest.Matchers.equalTo; @@ -6,10 +6,10 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -import org.baeldung.java8.entity.Human; import org.junit.Assert; import org.junit.Test; +import com.baeldung.java8.entity.Human; import com.google.common.collect.Lists; import com.google.common.primitives.Ints; diff --git a/core-java-8/src/test/java/org/baeldung/java8/JavaFolderSizeTest.java b/core-java-8/src/test/java/com/baeldung/java8/JavaFolderSizeTest.java similarity index 86% rename from core-java-8/src/test/java/org/baeldung/java8/JavaFolderSizeTest.java rename to core-java-8/src/test/java/com/baeldung/java8/JavaFolderSizeTest.java index baa41511de..2ac16b5d1d 100644 --- a/core-java-8/src/test/java/org/baeldung/java8/JavaFolderSizeTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/JavaFolderSizeTest.java @@ -1,4 +1,4 @@ -package org.baeldung.java8; +package com.baeldung.java8; import static org.junit.Assert.assertEquals; @@ -15,15 +15,24 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.stream.StreamSupport; import org.apache.commons.io.FileUtils; +import org.junit.Before; import org.junit.Test; public class JavaFolderSizeTest { + private String path; + + @Before + public void init() { + final String separator = File.separator; + path = "src" + separator + "test" + separator + "resources"; + } + @Test public void whenGetFolderSizeRecursive_thenCorrect() { final long expectedSize = 136; - final File folder = new File("src/test/resources"); + final File folder = new File(path); final long size = getFolderSize(folder); assertEquals(expectedSize, size); @@ -34,7 +43,7 @@ public class JavaFolderSizeTest { final long expectedSize = 136; final AtomicLong size = new AtomicLong(0); - final Path folder = Paths.get("src/test/resources"); + final Path folder = Paths.get(path); Files.walkFileTree(folder, new SimpleFileVisitor() { @Override @@ -51,7 +60,7 @@ public class JavaFolderSizeTest { public void whenGetFolderSizeUsingJava8_thenCorrect() throws IOException { final long expectedSize = 136; - final Path folder = Paths.get("src/test/resources"); + final Path folder = Paths.get(path); final long size = Files.walk(folder).filter(p -> p.toFile().isFile()).mapToLong(p -> p.toFile().length()).sum(); assertEquals(expectedSize, size); @@ -61,7 +70,7 @@ public class JavaFolderSizeTest { public void whenGetFolderSizeUsingApacheCommonsIO_thenCorrect() { final long expectedSize = 136; - final File folder = new File("src/test/resources"); + final File folder = new File(path); final long size = FileUtils.sizeOfDirectory(folder); assertEquals(expectedSize, size); @@ -71,7 +80,7 @@ public class JavaFolderSizeTest { public void whenGetFolderSizeUsingGuava_thenCorrect() { final long expectedSize = 136; - final File folder = new File("src/test/resources"); + final File folder = new File(path); final Iterable files = com.google.common.io.Files.fileTreeTraverser().breadthFirstTraversal(folder); final long size = StreamSupport.stream(files.spliterator(), false).filter(f -> f.isFile()).mapToLong(File::length).sum(); @@ -81,7 +90,7 @@ public class JavaFolderSizeTest { @Test public void whenGetReadableSize_thenCorrect() { - final File folder = new File("src/test/resources"); + final File folder = new File(path); final long size = getFolderSize(folder); final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" }; diff --git a/core-java-8/src/test/java/com/baeldung/java8/JavaTryWithResourcesTest.java b/core-java-8/src/test/java/com/baeldung/java8/JavaTryWithResourcesTest.java new file mode 100644 index 0000000000..18110b181d --- /dev/null +++ b/core-java-8/src/test/java/com/baeldung/java8/JavaTryWithResourcesTest.java @@ -0,0 +1,86 @@ +package com.baeldung.java8; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Date; +import java.util.Scanner; + +import org.junit.Assert; +import org.junit.Test; + +public class JavaTryWithResourcesTest { + + private static final String TEST_STRING_HELLO_WORLD = "Hello World"; + private Date resource1Date, resource2Date; + + // tests + + /* Example for using Try_with_resources */ + @Test + public void whenWritingToStringWriter_thenCorrectlyWritten() { + final StringWriter sw = new StringWriter(); + try (PrintWriter pw = new PrintWriter(sw, true)) { + pw.print(TEST_STRING_HELLO_WORLD); + } + + Assert.assertEquals(sw.getBuffer().toString(), TEST_STRING_HELLO_WORLD); + } + + /* Example for using multiple resources */ + @Test + public void givenStringToScanner_whenWritingToStringWriter_thenCorrectlyWritten() { + + final StringWriter sw = new StringWriter(); + try (Scanner sc = new Scanner(TEST_STRING_HELLO_WORLD); PrintWriter pw = new PrintWriter(sw, true)) { + while (sc.hasNext()) { + pw.print(sc.nextLine()); + } + } + + Assert.assertEquals(sw.getBuffer().toString(), TEST_STRING_HELLO_WORLD); + } + + /* Example to show order in which the resources are closed */ + @Test + public void whenFirstAutoClosableResourceIsinitializedFirst_thenFirstAutoClosableResourceIsReleasedFirst() throws Exception { + try (AutoCloseableResourcesFirst af = new AutoCloseableResourcesFirst(); AutoCloseableResourcesSecond as = new AutoCloseableResourcesSecond()) { + af.doSomething(); + as.doSomething(); + } + Assert.assertTrue(resource1Date.after(resource2Date)); + } + + class AutoCloseableResourcesFirst implements AutoCloseable { + public AutoCloseableResourcesFirst() { + System.out.println("Constructor -> AutoCloseableResources_First"); + } + + public void doSomething() { + System.out.println("Something -> AutoCloseableResources_First"); + } + + @Override + public void close() throws Exception { + System.out.println("Closed AutoCloseableResources_First"); + resource1Date = new Date(); + } + } + + class AutoCloseableResourcesSecond implements AutoCloseable { + public AutoCloseableResourcesSecond() { + System.out.println("Constructor -> AutoCloseableResources_Second"); + } + + public void doSomething() { + System.out.println("Something -> AutoCloseableResources_Second"); + } + + @Override + public void close() throws Exception { + System.out.println("Closed AutoCloseableResources_Second"); + resource2Date = new Date(); + Thread.sleep(10000); + } + } + +} diff --git a/core-java-8/src/test/java/org/baeldung/java8/base64/ApacheCommonsEncodeDecodeTest.java b/core-java-8/src/test/java/com/baeldung/java8/base64/ApacheCommonsEncodeDecodeTest.java similarity index 98% rename from core-java-8/src/test/java/org/baeldung/java8/base64/ApacheCommonsEncodeDecodeTest.java rename to core-java-8/src/test/java/com/baeldung/java8/base64/ApacheCommonsEncodeDecodeTest.java index 9745655d8a..07380cdd01 100644 --- a/core-java-8/src/test/java/org/baeldung/java8/base64/ApacheCommonsEncodeDecodeTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/base64/ApacheCommonsEncodeDecodeTest.java @@ -1,4 +1,4 @@ -package org.baeldung.java8.base64; +package com.baeldung.java8.base64; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; diff --git a/core-java-8/src/test/java/org/baeldung/java8/base64/Java8EncodeDecodeTest.java b/core-java-8/src/test/java/com/baeldung/java8/base64/Java8EncodeDecodeTest.java similarity index 99% rename from core-java-8/src/test/java/org/baeldung/java8/base64/Java8EncodeDecodeTest.java rename to core-java-8/src/test/java/com/baeldung/java8/base64/Java8EncodeDecodeTest.java index 7b7a0be26a..3c504edbf3 100644 --- a/core-java-8/src/test/java/org/baeldung/java8/base64/Java8EncodeDecodeTest.java +++ b/core-java-8/src/test/java/com/baeldung/java8/base64/Java8EncodeDecodeTest.java @@ -1,4 +1,4 @@ -package org.baeldung.java8.base64; +package com.baeldung.java8.base64; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; diff --git a/core-java-8/src/test/java/org/baeldung/java8/entity/Human.java b/core-java-8/src/test/java/com/baeldung/java8/entity/Human.java similarity index 98% rename from core-java-8/src/test/java/org/baeldung/java8/entity/Human.java rename to core-java-8/src/test/java/com/baeldung/java8/entity/Human.java index ac58b301b7..cab8546129 100644 --- a/core-java-8/src/test/java/org/baeldung/java8/entity/Human.java +++ b/core-java-8/src/test/java/com/baeldung/java8/entity/Human.java @@ -1,4 +1,4 @@ -package org.baeldung.java8.entity; +package com.baeldung.java8.entity; public class Human { private String name; diff --git a/core-java/README.md b/core-java/README.md index 772681ad57..23fe12465f 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -6,4 +6,10 @@ - [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list) - [Java - Reading a Large File Efficiently](http://www.baeldung.com/java-read-lines-large-file) - [Java InputStream to String](http://www.baeldung.com/convert-input-stream-to-string) - +- [Converting between an Array and a List in Java](http://www.baeldung.com/convert-array-to-list-and-list-to-array) +- [Converting between an Array and a Set in Java](http://www.baeldung.com/convert-array-to-set-and-set-to-array) +- [Converting between a List and a Set in Java](http://www.baeldung.com/convert-list-to-set-and-set-to-list) +- [Convert a Map to an Array, List or Set in Java](http://www.baeldung.com/convert-map-values-to-array-list-set) +- [Java – Write to File](http://www.baeldung.com/java-write-to-file) +- [Java Scanner](http://www.baeldung.com/java-scanner) +- [Java Timer](http://www.baeldung.com/java-timer-and-timertask) diff --git a/core-java/pom.xml b/core-java/pom.xml index c6f2b32cd8..b439b41f22 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -79,7 +79,7 @@ junit - junit-dep + junit ${junit.version} test @@ -152,22 +152,22 @@ 5.1.35 - 2.4.4 + 2.5.5 - 1.7.12 + 1.7.13 1.1.3 5.1.3.Final - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 diff --git a/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java b/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java index 53bbe8a8d3..55a0904499 100644 --- a/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java +++ b/core-java/src/test/java/org/baeldung/java/io/JavaInputStreamToXUnitTest.java @@ -32,7 +32,6 @@ import com.google.common.io.ByteSource; import com.google.common.io.ByteStreams; import com.google.common.io.CharStreams; import com.google.common.io.Files; -import com.google.common.io.InputSupplier; @SuppressWarnings("unused") public class JavaInputStreamToXUnitTest { @@ -75,16 +74,14 @@ public class JavaInputStreamToXUnitTest { final String originalString = randomAlphabetic(DEFAULT_SIZE); final InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); - final InputSupplier inputSupplier = new InputSupplier() { + final ByteSource byteSource = new ByteSource() { @Override - public final InputStream getInput() throws IOException { + public final InputStream openStream() throws IOException { return inputStream; } }; - final InputSupplier readerSupplier = CharStreams.newReaderSupplier(inputSupplier, Charsets.UTF_8); - // When - final String text = CharStreams.toString(readerSupplier); + final String text = byteSource.asCharSource(Charsets.UTF_8).read(); assertThat(text, equalTo(originalString)); } diff --git a/gson/README.md b/gson/README.md index 559e536d81..67651b732e 100644 --- a/gson/README.md +++ b/gson/README.md @@ -2,5 +2,6 @@ ## GSON Cookbooks and Examples -### Relevant Articles: +### Relevant Articles: +- [Gson Deserialization Cookbook](http://www.baeldung.com/gson-deserialization-guide) diff --git a/gson/pom.xml b/gson/pom.xml index 500d14c40c..c0640abcbf 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -53,7 +53,7 @@ junit - junit-dep + junit ${junit.version} test @@ -124,19 +124,19 @@ 2.3 - 1.7.12 + 1.7.13 1.1.3 5.1.3.Final - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 diff --git a/gson/src/test/java/org/baeldung/gson/deserialization/Foo.java b/gson/src/test/java/org/baeldung/gson/deserialization/Foo.java index 64720f63f9..84f8aaef13 100644 --- a/gson/src/test/java/org/baeldung/gson/deserialization/Foo.java +++ b/gson/src/test/java/org/baeldung/gson/deserialization/Foo.java @@ -9,6 +9,10 @@ public class Foo { this.stringValue = stringValue; } + public Foo(final String stringValue) { + this.stringValue = stringValue; + } + public Foo() { super(); } @@ -19,27 +23,33 @@ public class Foo { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + intValue; - result = prime * result + ((stringValue == null) ? 0 : stringValue.hashCode()); + result = (prime * result) + intValue; + result = (prime * result) + ((stringValue == null) ? 0 : stringValue.hashCode()); return result; } @Override public boolean equals(final Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } final Foo other = (Foo) obj; - if (intValue != other.intValue) + if (intValue != other.intValue) { return false; + } if (stringValue == null) { - if (other.stringValue != null) + if (other.stringValue != null) { return false; - } else if (!stringValue.equals(other.stringValue)) + } + } else if (!stringValue.equals(other.stringValue)) { return false; + } return true; } diff --git a/gson/src/test/java/org/baeldung/gson/deserialization/FooInstanceCreator.java b/gson/src/test/java/org/baeldung/gson/deserialization/FooInstanceCreator.java new file mode 100644 index 0000000000..4df3986ec3 --- /dev/null +++ b/gson/src/test/java/org/baeldung/gson/deserialization/FooInstanceCreator.java @@ -0,0 +1,14 @@ +package org.baeldung.gson.deserialization; + +import java.lang.reflect.Type; + +import com.google.gson.InstanceCreator; + +public class FooInstanceCreator implements InstanceCreator { + + @Override + public Foo createInstance(Type type) { + return new Foo("sample"); + } + +} diff --git a/gson/src/test/java/org/baeldung/gson/deserialization/FooWithInner.java b/gson/src/test/java/org/baeldung/gson/deserialization/FooWithInner.java new file mode 100644 index 0000000000..705e534e77 --- /dev/null +++ b/gson/src/test/java/org/baeldung/gson/deserialization/FooWithInner.java @@ -0,0 +1,24 @@ +package org.baeldung.gson.deserialization; + +public class FooWithInner { + public int intValue; + public String stringValue; + public InnerFoo innerFoo; + + public FooWithInner(int intValue, String stringValue, String name) { + super(); + this.intValue = intValue; + this.stringValue = stringValue; + this.innerFoo = new InnerFoo(name); + } + + public class InnerFoo { + public String name; + + public InnerFoo(String name) { + super(); + this.name = name; + } + + } +} diff --git a/gson/src/test/java/org/baeldung/gson/deserialization/test/GsonDeserializationTest.java b/gson/src/test/java/org/baeldung/gson/deserialization/test/GsonDeserializationTest.java index 342b3096d7..072a25e749 100644 --- a/gson/src/test/java/org/baeldung/gson/deserialization/test/GsonDeserializationTest.java +++ b/gson/src/test/java/org/baeldung/gson/deserialization/test/GsonDeserializationTest.java @@ -12,6 +12,8 @@ import java.util.Collection; import org.baeldung.gson.deserialization.Foo; import org.baeldung.gson.deserialization.FooDeserializerFromJsonWithDifferentFields; +import org.baeldung.gson.deserialization.FooInstanceCreator; +import org.baeldung.gson.deserialization.FooWithInner; import org.baeldung.gson.deserialization.GenericFoo; import org.junit.Test; @@ -108,4 +110,29 @@ public class GsonDeserializationTest { assertEquals(targetObject.stringValue, "seven"); } + // new examples + + @Test + public void whenDeserializingToNestedObjects_thenCorrect() { + final String json = "{\"intValue\":1,\"stringValue\":\"one\",\"innerFoo\":{\"name\":\"inner\"}}"; + + final FooWithInner targetObject = new Gson().fromJson(json, FooWithInner.class); + + assertEquals(targetObject.intValue, 1); + assertEquals(targetObject.stringValue, "one"); + assertEquals(targetObject.innerFoo.name, "inner"); + } + + @Test + public void whenDeserializingUsingInstanceCreator_thenCorrect() { + final String json = "{\"intValue\":1}"; + + final GsonBuilder gsonBldr = new GsonBuilder(); + gsonBldr.registerTypeAdapter(Foo.class, new FooInstanceCreator()); + final Foo targetObject = gsonBldr.create().fromJson(json, Foo.class); + + assertEquals(targetObject.intValue, 1); + assertEquals(targetObject.stringValue, "sample"); + } + } diff --git a/guava/README.md b/guava/README.md index 8960b4676e..28bcfeb912 100644 --- a/guava/README.md +++ b/guava/README.md @@ -7,7 +7,11 @@ - [Guava Collections Cookbook](http://www.baeldung.com/guava-collections) - [Guava Ordering Cookbook](http://www.baeldung.com/guava-order) - [Guava Functional Cookbook](http://www.baeldung.com/guava-functions-predicates) - - [Hamcrest Collections Cookbook](http://www.baeldung.com/hamcrest-collections-arrays) - - [Partition a List in Java](http://www.baeldung.com/java-list-split) +- [Filtering and Transforming Collections in Guava](http://www.baeldung.com/guava-filter-and-transform-a-collection) +- [Guava – Join and Split Collections](http://www.baeldung.com/guava-joiner-and-splitter-tutorial) +- [Guava – Write to File, Read from File](http://www.baeldung.com/guava-write-to-file-read-from-file) +- [Guava – Lists](http://www.baeldung.com/guava-lists) +- [Guava – Sets](http://www.baeldung.com/guava-sets) +- [Guava – Maps](http://www.baeldung.com/guava-maps) diff --git a/guava/pom.xml b/guava/pom.xml index 78c5a14e41..2b07be71bf 100644 --- a/guava/pom.xml +++ b/guava/pom.xml @@ -34,7 +34,7 @@ junit - junit-dep + junit ${junit.version} test @@ -102,19 +102,19 @@ 5.1.35 - 1.7.12 + 1.7.13 1.1.3 5.1.3.Final - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 diff --git a/guava/src/test/java/org/baeldung/guava/GuavaCollectionTypesTest.java b/guava/src/test/java/org/baeldung/guava/GuavaCollectionTypesTest.java index 26d3fa90ca..9c38afbcc2 100644 --- a/guava/src/test/java/org/baeldung/guava/GuavaCollectionTypesTest.java +++ b/guava/src/test/java/org/baeldung/guava/GuavaCollectionTypesTest.java @@ -148,6 +148,15 @@ public class GuavaCollectionTypesTest { assertThat(intersection, containsInAnyOrder('b', 'c')); } + @Test + public void whenCalculatingSetSymmetricDifference_thenCorrect() { + final Set first = ImmutableSet.of('a', 'b', 'c'); + final Set second = ImmutableSet.of('b', 'c', 'd'); + + final Set intersection = Sets.symmetricDifference(first, second); + assertThat(intersection, containsInAnyOrder('a', 'd')); + } + @Test public void whenCalculatingPowerSet_thenCorrect() { final Set chars = ImmutableSet.of('a', 'b'); 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/guava18/README.md b/guava18/README.md new file mode 100644 index 0000000000..9924d7c16f --- /dev/null +++ b/guava18/README.md @@ -0,0 +1,12 @@ +========= + +## Guava and Hamcrest Cookbooks and Examples + + +### Relevant Articles: +- [Guava Collections Cookbook](http://www.baeldung.com/guava-collections) +- [Guava Ordering Cookbook](http://www.baeldung.com/guava-order) +- [Guava Functional Cookbook](http://www.baeldung.com/guava-functions-predicates) +- [Hamcrest Collections Cookbook](http://www.baeldung.com/hamcrest-collections-arrays) +- [Partition a List in Java](http://www.baeldung.com/java-list-split) +- [Guava 18: What’s New?](http://www.baeldung.com/whats-new-in-guava-18) diff --git a/guava18/pom.xml b/guava18/pom.xml new file mode 100644 index 0000000000..21f4697a73 --- /dev/null +++ b/guava18/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + com.baeldung + guava + 1.0-SNAPSHOT + + + + com.google.guava + guava + 18.0 + + + junit + junit + 4.12 + + + + + + maven-compiler-plugin + 3.3 + + true + true + 1.8 + 1.8 + UTF-8 + true + true + + + + + + \ No newline at end of file diff --git a/guava18/src/main/java/com/baeldung/guava/entity/Administrator.java b/guava18/src/main/java/com/baeldung/guava/entity/Administrator.java new file mode 100644 index 0000000000..f9447ea44d --- /dev/null +++ b/guava18/src/main/java/com/baeldung/guava/entity/Administrator.java @@ -0,0 +1,18 @@ +package com.baeldung.guava.entity; + +import com.google.common.base.MoreObjects; + +public class Administrator extends User{ + public Administrator(long id, String name, int age) { + super(id, name, age); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("id", getId()) + .add("name", getName()) + .add("age", getAge()) + .toString(); + } +} \ No newline at end of file diff --git a/guava18/src/main/java/com/baeldung/guava/entity/Player.java b/guava18/src/main/java/com/baeldung/guava/entity/Player.java new file mode 100644 index 0000000000..f460fa9f00 --- /dev/null +++ b/guava18/src/main/java/com/baeldung/guava/entity/Player.java @@ -0,0 +1,8 @@ +package com.baeldung.guava.entity; + +public class Player extends User{ + public Player(long id, String name, int age) { + super(id, name, age); + } + +} diff --git a/guava18/src/main/java/com/baeldung/guava/entity/User.java b/guava18/src/main/java/com/baeldung/guava/entity/User.java new file mode 100644 index 0000000000..be673edb10 --- /dev/null +++ b/guava18/src/main/java/com/baeldung/guava/entity/User.java @@ -0,0 +1,36 @@ +package com.baeldung.guava.entity; + +import com.google.common.base.MoreObjects; + +public class User{ + private long id; + private String name; + private int age; + + public User(long id, String name, int age) { + this.id = id; + this.name = name; + this.age = age; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(User.class) + .add("id", id) + .add("name", name) + .add("age", age) + .toString(); + } +} \ No newline at end of file diff --git a/guava18/src/test/java/com/baeldung/guava/FluentIterableTest.java b/guava18/src/test/java/com/baeldung/guava/FluentIterableTest.java new file mode 100644 index 0000000000..82552fca8f --- /dev/null +++ b/guava18/src/test/java/com/baeldung/guava/FluentIterableTest.java @@ -0,0 +1,80 @@ +package com.baeldung.guava; + +import com.baeldung.guava.entity.User; +import com.google.common.base.Functions; +import com.google.common.base.Joiner; +import com.google.common.base.Predicate; +import com.google.common.collect.FluentIterable; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.CoreMatchers.equalTo; + +public class FluentIterableTest { + + private static final int ADULT_AGE = 18; + + @Test + public void whenFilteringByAge_shouldFilterOnlyAdultUsers() throws Exception { + List users = new ArrayList<>(); + users.add(new User(1L, "John", 45)); + users.add(new User(2L, "Michael", 27)); + users.add(new User(3L, "Max", 16)); + users.add(new User(4L, "Bob", 10)); + users.add(new User(5L, "Bill", 65)); + + Predicate byAge = input -> input.getAge() > ADULT_AGE; + + List results = FluentIterable.from(users) + .filter(byAge) + .transform(Functions.toStringFunction()) + .toList(); + + Assert.assertThat(results.size(), equalTo(3)); + } + + @Test + public void whenCreatingFluentIterableFromArray_shouldContainAllUsers() throws Exception { + User[] usersArray = {new User(1L, "John", 45), new User(2L, "Max", 15)}; + FluentIterable users = FluentIterable.of(usersArray); + + Assert.assertThat(users.size(), equalTo(2)); + } + + @Test + public void whenAppendingElementsToFluentIterable_shouldContainAllUsers() throws Exception { + User[] usersArray = {new User(1L, "John", 45), new User(2L, "Max", 15)}; + + FluentIterable users = FluentIterable.of(usersArray).append( + new User(3L, "Bob", 23), + new User(4L, "Bill", 17) + ); + + Assert.assertThat(users.size(), equalTo(4)); + } + + @Test + public void whenAppendingListToFluentIterable_shouldContainAllUsers() throws Exception { + User[] usersArray = {new User(1L, "John", 45), new User(2L, "Max", 15)}; + + List usersList = new ArrayList<>(); + usersList.add(new User(3L, "David", 32)); + + FluentIterable users = FluentIterable.of(usersArray).append(usersList); + + Assert.assertThat(users.size(), equalTo(3)); + } + + @Test + public void whenJoiningFluentIterableElements_shouldOutputAllUsers() throws Exception { + User[] usersArray = {new User(1L, "John", 45), new User(2L, "Max", 15)}; + + FluentIterable users = FluentIterable.of(usersArray); + + Assert.assertThat(users.join(Joiner.on("; ")), + equalTo("User{id=1, name=John, age=45}; User{id=2, name=Max, age=15}")); + } +} \ No newline at end of file diff --git a/guava18/src/test/java/com/baeldung/guava/GuavaMiscUtilsTest.java b/guava18/src/test/java/com/baeldung/guava/GuavaMiscUtilsTest.java new file mode 100644 index 0000000000..db82ea6da8 --- /dev/null +++ b/guava18/src/test/java/com/baeldung/guava/GuavaMiscUtilsTest.java @@ -0,0 +1,41 @@ +package com.baeldung.guava; + +import com.google.common.hash.HashCode; +import com.google.common.hash.Hashing; +import com.google.common.net.InetAddresses; +import org.junit.Assert; +import org.junit.Test; + +import java.net.InetAddress; +import java.util.concurrent.ConcurrentHashMap; + +import static org.hamcrest.CoreMatchers.equalTo; + +public class GuavaMiscUtilsTest { + @Test + public void whenHashingData_shouldReturnCorrectHashCode() throws Exception { + int receivedData = 123; + + HashCode hashCode = Hashing.crc32c().hashInt(receivedData); + Assert.assertThat(hashCode.toString(), equalTo("495be649")); + } + + @Test + public void whenDecrementingIpAddress_shouldReturnOneLessIpAddress() throws Exception { + InetAddress address = InetAddress.getByName("127.0.0.5"); + InetAddress decrementedAddress = InetAddresses.decrement(address); + + Assert.assertThat(decrementedAddress.toString(), equalTo("/127.0.0.4")); + } + + @Test + public void whenExecutingRunnableInThread_shouldLogThreadExecution() throws Exception { + ConcurrentHashMap threadExecutions = new ConcurrentHashMap<>(); + Runnable logThreadRun = () -> threadExecutions.put(Thread.currentThread().getName(), true); + + Thread t = new Thread(logThreadRun); + t.run(); + + Assert.assertTrue(threadExecutions.get("main")); + } +} diff --git a/guava18/src/test/java/com/baeldung/guava/MoreExecutorsTest.java b/guava18/src/test/java/com/baeldung/guava/MoreExecutorsTest.java new file mode 100644 index 0000000000..ec173499f1 --- /dev/null +++ b/guava18/src/test/java/com/baeldung/guava/MoreExecutorsTest.java @@ -0,0 +1,51 @@ +package com.baeldung.guava; + +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.*; + +public class MoreExecutorsTest { + @Test + public void whenExecutingRunnableInThreadPool_shouldLogAllThreadsExecutions() throws Exception { + ConcurrentHashMap threadExecutions = new ConcurrentHashMap<>(); + + Runnable logThreadRun = () -> threadExecutions.put(Thread.currentThread().getName(), true); + + ExecutorService executorService = Executors.newFixedThreadPool(2); + executorService.submit(logThreadRun); + executorService.submit(logThreadRun); + executorService.shutdown(); + + executorService.awaitTermination(100, TimeUnit.MILLISECONDS); + + Assert.assertTrue(threadExecutions.get("pool-1-thread-1")); + Assert.assertTrue(threadExecutions.get("pool-1-thread-2")); + } + + @Test + public void whenExecutingRunnableInDirectExecutor_shouldLogThreadExecution() throws Exception { + ConcurrentHashMap threadExecutions = new ConcurrentHashMap<>(); + + Runnable logThreadRun = () -> threadExecutions.put(Thread.currentThread().getName(), true); + + Executor executor = MoreExecutors.directExecutor(); + executor.execute(logThreadRun); + + Assert.assertTrue(threadExecutions.get("main")); + } + + @Test + public void whenExecutingRunnableInListeningExecutor_shouldLogThreadExecution() throws Exception { + ConcurrentHashMap threadExecutions = new ConcurrentHashMap<>(); + + Runnable logThreadRun = () -> threadExecutions.put(Thread.currentThread().getName(), true); + + ListeningExecutorService executor = MoreExecutors.newDirectExecutorService(); + executor.execute(logThreadRun); + + Assert.assertTrue(threadExecutions.get("main")); + } +} diff --git a/guava18/src/test/java/com/baeldung/guava/MoreObjectsTest.java b/guava18/src/test/java/com/baeldung/guava/MoreObjectsTest.java new file mode 100644 index 0000000000..5e46b5aba9 --- /dev/null +++ b/guava18/src/test/java/com/baeldung/guava/MoreObjectsTest.java @@ -0,0 +1,33 @@ +package com.baeldung.guava; + +import com.baeldung.guava.entity.Administrator; +import com.baeldung.guava.entity.Player; +import com.baeldung.guava.entity.User; +import org.junit.Assert; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.equalTo; + +public class MoreObjectsTest { + + @Test + public void whenToString_shouldIncludeAllFields() throws Exception { + User user = new User(12L, "John Doe", 25); + + Assert.assertThat(user.toString(), equalTo("User{id=12, name=John Doe, age=25}")); + } + + @Test + public void whenPlayerToString_shouldCallParentToString() throws Exception { + User user = new Player(12L, "John Doe", 25); + + Assert.assertThat(user.toString(), equalTo("User{id=12, name=John Doe, age=25}")); + } + + @Test + public void whenAdministratorToString_shouldExecuteAdministratorToString() throws Exception { + User user = new Administrator(12L, "John Doe", 25); + + Assert.assertThat(user.toString(), equalTo("Administrator{id=12, name=John Doe, age=25}")); + } +} diff --git a/guava19/pom.xml b/guava19/pom.xml new file mode 100644 index 0000000000..97c1b0ea4e --- /dev/null +++ b/guava19/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + com.baeldung + guava + 1.0-SNAPSHOT + + + + com.google.guava + guava + 19.0 + + + junit + junit + 4.12 + + + org.hamcrest + hamcrest-all + 1.3 + + + + + + maven-compiler-plugin + 3.3 + + true + true + 1.8 + 1.8 + UTF-8 + true + true + + + + + + \ No newline at end of file diff --git a/guava19/src/main/java/com/baeldung/guava/entity/User.java b/guava19/src/main/java/com/baeldung/guava/entity/User.java new file mode 100644 index 0000000000..be673edb10 --- /dev/null +++ b/guava19/src/main/java/com/baeldung/guava/entity/User.java @@ -0,0 +1,36 @@ +package com.baeldung.guava.entity; + +import com.google.common.base.MoreObjects; + +public class User{ + private long id; + private String name; + private int age; + + public User(long id, String name, int age) { + this.id = id; + this.name = name; + this.age = age; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(User.class) + .add("id", id) + .add("name", name) + .add("age", age) + .toString(); + } +} \ No newline at end of file diff --git a/guava19/src/test/java/com/baeldung/guava/CharMatcherTest.java b/guava19/src/test/java/com/baeldung/guava/CharMatcherTest.java new file mode 100644 index 0000000000..f890d9abc1 --- /dev/null +++ b/guava19/src/test/java/com/baeldung/guava/CharMatcherTest.java @@ -0,0 +1,33 @@ +package com.baeldung.guava; + +import com.google.common.base.CharMatcher; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class CharMatcherTest { + @Test + public void whenMatchingLetterOrString_ShouldReturnTrueForCorrectString() throws Exception { + String inputString = "someString789"; + boolean result = CharMatcher.javaLetterOrDigit().matchesAllOf(inputString); + + assertTrue(result); + } + + @Test + public void whenCollapsingString_ShouldReturnStringWithDashesInsteadOfWhitespaces() throws Exception { + String inputPhoneNumber = "8 123 456 123"; + String result = CharMatcher.whitespace().collapseFrom(inputPhoneNumber, '-'); + + assertEquals("8-123-456-123", result); + } + + @Test + public void whenCountingDigitsInString_ShouldReturnActualCountOfDigits() throws Exception { + String inputPhoneNumber = "8 123 456 123"; + int result = CharMatcher.digit().countIn(inputPhoneNumber); + + assertEquals(10, result); + } +} diff --git a/guava19/src/test/java/com/baeldung/guava/GuavaMiscUtilsTest.java b/guava19/src/test/java/com/baeldung/guava/GuavaMiscUtilsTest.java new file mode 100644 index 0000000000..c7b8441b78 --- /dev/null +++ b/guava19/src/test/java/com/baeldung/guava/GuavaMiscUtilsTest.java @@ -0,0 +1,88 @@ +package com.baeldung.guava; + +import com.google.common.base.Throwables; +import com.google.common.collect.*; +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; +import static org.hamcrest.core.AnyOf.anyOf; +import static org.junit.Assert.*; + +public class GuavaMiscUtilsTest { + + @Test + public void whenGettingLazyStackTrace_ListShouldBeReturned() throws Exception { + IllegalArgumentException e = new IllegalArgumentException("Some argument is incorrect"); + + List stackTraceElements = Throwables.lazyStackTrace(e); + + assertTrue(stackTraceElements.size() > 0); + } + + @Test + public void multisetShouldCountHitsOfMultipleDuplicateObjects() throws Exception { + List userNames = Arrays.asList("David", "Eugene", "Alex", "Alex", "David", "David", "David"); + + Multiset userNamesMultiset = HashMultiset.create(userNames); + + assertEquals(7, userNamesMultiset.size()); + assertEquals(4, userNamesMultiset.count("David")); + assertEquals(2, userNamesMultiset.count("Alex")); + assertEquals(1, userNamesMultiset.count("Eugene")); + assertThat(userNamesMultiset.elementSet(), anyOf(containsInAnyOrder("Alex", "David", "Eugene"))); + } + + @Test + public void whenAddingNewConnectedRange_RangesShouldBeMerged() throws Exception { + RangeSet rangeSet = TreeRangeSet.create(); + + rangeSet.add(Range.closed(1, 10)); + rangeSet.add(Range.closed(5, 15)); + rangeSet.add(Range.closedOpen(10, 17)); + + assertTrue(rangeSet.encloses(Range.closedOpen(1, 17))); + assertTrue(rangeSet.encloses(Range.closed(2, 3))); + assertTrue(rangeSet.contains(15)); + assertFalse(rangeSet.contains(17)); + assertEquals(1, rangeSet.asDescendingSetOfRanges().size()); + } + + @Test + public void cartesianProductShouldReturnAllPossibleCombinations() throws Exception { + List first = Lists.newArrayList("value1", "value2"); + List second = Lists.newArrayList("value3", "value4"); + + List> cartesianProduct = Lists.cartesianProduct(first, second); + + List pair1 = Lists.newArrayList("value2", "value3"); + List pair2 = Lists.newArrayList("value2", "value4"); + List pair3 = Lists.newArrayList("value1", "value3"); + List pair4 = Lists.newArrayList("value1", "value4"); + + assertThat(cartesianProduct, anyOf(containsInAnyOrder(pair1, pair2, pair3, pair4))); + } + + @Test + public void multisetShouldRemoveOccurrencesOfSpecifiedObjects() throws Exception { + Multiset multisetToModify = HashMultiset.create(); + Multiset occurrencesToRemove = HashMultiset.create(); + + multisetToModify.add("John"); + multisetToModify.add("Max"); + multisetToModify.add("Alex"); + + occurrencesToRemove.add("Alex"); + occurrencesToRemove.add("John"); + + Multisets.removeOccurrences(multisetToModify, occurrencesToRemove); + + assertEquals(1, multisetToModify.size()); + assertTrue(multisetToModify.contains("Max")); + assertFalse(multisetToModify.contains("John")); + assertFalse(multisetToModify.contains("Alex")); + } +} \ No newline at end of file diff --git a/guava19/src/test/java/com/baeldung/guava/HashingTest.java b/guava19/src/test/java/com/baeldung/guava/HashingTest.java new file mode 100644 index 0000000000..9b4acde9f7 --- /dev/null +++ b/guava19/src/test/java/com/baeldung/guava/HashingTest.java @@ -0,0 +1,34 @@ +package com.baeldung.guava; + +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hashing; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class HashingTest { + @Test + public void whenHashingInSha384_hashFunctionShouldBeReturned() throws Exception { + int inputData = 15; + + HashFunction hashFunction = Hashing.sha384(); + HashCode hashCode = hashFunction.hashInt(inputData); + + assertEquals("0904b6277381dcfbdddd6b6c66e4e3e8f83d4690718d8e6f272c891f24773a12feaf8c449fa6e42240a621b2b5e3cda8", + hashCode.toString()); + } + + @Test + public void whenConcatenatingHashFunction_concatenatedHashShouldBeReturned() throws Exception { + int inputData = 15; + + HashFunction hashFunction = Hashing.concatenating(Hashing.crc32(), Hashing.crc32()); + HashFunction crc32Function = Hashing.crc32(); + + HashCode hashCode = hashFunction.hashInt(inputData); + HashCode crc32HashCode = crc32Function.hashInt(inputData); + + assertEquals(crc32HashCode.toString() + crc32HashCode.toString(), hashCode.toString()); + } +} diff --git a/guava19/src/test/java/com/baeldung/guava/TypeTokenTest.java b/guava19/src/test/java/com/baeldung/guava/TypeTokenTest.java new file mode 100644 index 0000000000..1923451f20 --- /dev/null +++ b/guava19/src/test/java/com/baeldung/guava/TypeTokenTest.java @@ -0,0 +1,45 @@ +package com.baeldung.guava; + +import com.google.common.reflect.TypeToken; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class TypeTokenTest { + @Test + public void whenCheckingIsAssignableFrom_shouldReturnTrueEvenIfGenericIsSpecified() throws Exception { + ArrayList stringList = new ArrayList<>(); + ArrayList intList = new ArrayList<>(); + boolean isAssignableFrom = stringList.getClass().isAssignableFrom(intList.getClass()); + + assertTrue(isAssignableFrom); + } + + @Test + public void whenCheckingIsSupertypeOf_shouldReturnFalseIfGenericIsSpecified() throws Exception { + TypeToken> listString = new TypeToken>() { + }; + TypeToken> integerString = new TypeToken>() { + }; + + boolean isSupertypeOf = listString.isSupertypeOf(integerString); + + assertFalse(isSupertypeOf); + } + + @Test + public void whenCheckingIsSubtypeOf_shouldReturnTrueIfClassIsExtendedFrom() throws Exception { + TypeToken> stringList = new TypeToken>() { + }; + TypeToken list = new TypeToken() { + }; + + boolean isSubtypeOf = stringList.isSubtypeOf(list); + + assertTrue(isSubtypeOf); + } +} diff --git a/handling-spring-static-resources/.classpath b/handling-spring-static-resources/.classpath index 88536687a5..71a1c1e0b5 100644 --- a/handling-spring-static-resources/.classpath +++ b/handling-spring-static-resources/.classpath @@ -19,9 +19,9 @@ - + - + diff --git a/handling-spring-static-resources/pom.xml b/handling-spring-static-resources/pom.xml index 67591e1844..8efacc4b28 100644 --- a/handling-spring-static-resources/pom.xml +++ b/handling-spring-static-resources/pom.xml @@ -171,41 +171,37 @@ - 1.7 + 1.8 - 4.1.5.RELEASE - 3.2.5.RELEASE + 4.2.4.RELEASE + 4.0.3.RELEASE 1.8.1 2.3.2-b01 - - 4.1.5.RELEASE - 3.2.5.RELEASE - - 4.3.10.Final - 5.1.35 - 1.7.2.RELEASE + 4.3.11.Final + 5.1.37 + 1.9.2.RELEASE - 2.4.4 + 2.6.4 - 1.7.12 + 1.7.13 1.1.3 - 5.1.3.Final + 5.2.2.Final - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 diff --git a/handling-spring-static-resources/src/main/resources/webSecurityConfig.xml b/handling-spring-static-resources/src/main/resources/webSecurityConfig.xml index 56d7f9c113..76b5015e7b 100644 --- a/handling-spring-static-resources/src/main/resources/webSecurityConfig.xml +++ b/handling-spring-static-resources/src/main/resources/webSecurityConfig.xml @@ -2,10 +2,10 @@ @@ -21,7 +21,7 @@ - + diff --git a/handling-spring-static-resources/src/main/webapp/WEB-INF/view/login.jsp b/handling-spring-static-resources/src/main/webapp/WEB-INF/view/login.jsp index 1b09f7c634..8c9f46c027 100644 --- a/handling-spring-static-resources/src/main/webapp/WEB-INF/view/login.jsp +++ b/handling-spring-static-resources/src/main/webapp/WEB-INF/view/login.jsp @@ -41,15 +41,15 @@

-
+ - + - + diff --git a/httpclient/README.md b/httpclient/README.md index 529ac754f8..e06c57da71 100644 --- a/httpclient/README.md +++ b/httpclient/README.md @@ -5,12 +5,15 @@ ### Relevant Articles: -- [HttpClient 4 – Send Custom Cookie](http://www.baeldung.com/httpclient-4-cookies) -- [HttpClient 4 – Get the Status Code](http://www.baeldung.com/httpclient-status-code) -- [HttpClient 4 – Cancel / Abort Request](http://www.baeldung.com/httpclient-cancel-request) +- [HttpClient 4 – Send Custom Cookie](http://www.baeldung.com/httpclient-4-cookies) +- [HttpClient 4 – Get the Status Code](http://www.baeldung.com/httpclient-status-code) +- [HttpClient 4 – Cancel / Abort Request](http://www.baeldung.com/httpclient-cancel-request) - [HttpClient 4 Cookbook](http://www.baeldung.com/httpclient4) - [Unshorten URLs with HttpClient](http://www.baeldung.com/unshorten-url-httpclient) - [HttpClient with SSL](http://www.baeldung.com/httpclient-ssl) -- [HttpClient 4 – Follow Redirects for POST](http://www.baeldung.com/httpclient-redirect-on-http-post) -- [HttpClient – Set Custom Header](http://www.baeldung.com/httpclient-custom-http-header) +- [HttpClient 4 – Follow Redirects for POST](http://www.baeldung.com/httpclient-redirect-on-http-post) +- [HttpClient – Set Custom Header](http://www.baeldung.com/httpclient-custom-http-header) - [HttpClient Basic Authentication](http://www.baeldung.com/httpclient-4-basic-authentication) +- [Multipart Upload with HttpClient 4](http://www.baeldung.com/httpclient-multipart-upload) +- [HttpAsyncClient Tutorial](http://www.baeldung.com/httpasyncclient-tutorial) +- [HttpClient 4 Tutorial](http://www.baeldung.com/httpclient-guide) diff --git a/httpclient/pom.xml b/httpclient/pom.xml index a6df3842fd..0098c40d52 100644 --- a/httpclient/pom.xml +++ b/httpclient/pom.xml @@ -89,7 +89,7 @@ junit - junit-dep + junit ${junit.version} test @@ -157,19 +157,19 @@ 5.1.35 - 1.7.12 + 1.7.131.1.35.1.3.Final - 18.0 + 19.03.41.3 - 4.11 + 4.121.10.194.4.1 diff --git a/jackson/README.md b/jackson/README.md index 539cb34761..53b9c7c31d 100644 --- a/jackson/README.md +++ b/jackson/README.md @@ -4,9 +4,15 @@ ### Relevant Articles: - [Jackson Ignore Properties on Marshalling](http://www.baeldung.com/jackson-ignore-properties-on-serialization) -- [Jackson – Unmarshall to Collection/Array](http://www.baeldung.com/jackson-collection-array) +- [Jackson – Unmarshall to Collection/Array](http://www.baeldung.com/jackson-collection-array) - [Jackson Unmarshalling json with Unknown Properties](http://www.baeldung.com/jackson-deserialize-json-unknown-properties) -- [Jackson – Custom Serializer](http://www.baeldung.com/jackson-custom-serialization) -- [Jackson – Custom Deserializer](http://www.baeldung.com/jackson-deserialization) - - +- [Jackson – Custom Serializer](http://www.baeldung.com/jackson-custom-serialization) +- [Jackson – Custom Deserializer](http://www.baeldung.com/jackson-deserialization) +- [Jackson Exceptions – Problems and Solutions](http://www.baeldung.com/jackson-exception) +- [Jackson Date](http://www.baeldung.com/jackson-serialize-dates) +- [Jackson – Bidirectional Relationships](http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion) +- [Jackson JSON Tutorial](http://www.baeldung.com/jackson) +- [Jackson – Working with Maps and nulls](http://www.baeldung.com/jackson-map-null-values-or-null-key) +- [Jackson – Decide What Fields Get Serialized/Deserializaed](http://www.baeldung.com/jackson-field-serializable-deserializable-or-not) +- [A Guide to Jackson Annotations](http://www.baeldung.com/jackson-annotations) +- [Working with Tree Model Nodes in Jackson](http://www.baeldung.com/jackson-json-node-tree-model) diff --git a/jackson/pom.xml b/jackson/pom.xml index b2c2465436..ed7a5944a5 100644 --- a/jackson/pom.xml +++ b/jackson/pom.xml @@ -72,7 +72,7 @@ junit - junit-dep + junit ${junit.version} test @@ -140,22 +140,22 @@ 5.1.35 - 2.4.4 + 2.7.1-1 - 1.7.12 + 1.7.131.1.35.1.3.Final - 18.0 + 19.03.41.3 - 4.11 + 4.121.10.194.4.1 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/date/CustomDateDeserializer.java b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateDeserializer.java index bbd039f6ae..eb1866026f 100644 --- a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateDeserializer.java +++ b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateDeserializer.java @@ -12,7 +12,7 @@ import com.fasterxml.jackson.databind.JsonDeserializer; public class CustomDateDeserializer extends JsonDeserializer { - private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); @Override public Date deserialize(final JsonParser jsonparser, final DeserializationContext context) throws IOException, JsonProcessingException { diff --git a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateSerializer.java b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateSerializer.java index fc7cbb2db1..40aad21482 100644 --- a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateSerializer.java +++ b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateSerializer.java @@ -11,7 +11,7 @@ import com.fasterxml.jackson.databind.SerializerProvider; public class CustomDateSerializer extends JsonSerializer { - private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); @Override public void serialize(final Date value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException { diff --git a/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/Address.java b/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/Address.java new file mode 100644 index 0000000000..41ea8e7be3 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/Address.java @@ -0,0 +1,41 @@ +package org.baeldung.jackson.dynamicIgnore; + + +public class Address implements Hidable { + private String city; + private String country; + private boolean hidden; + + public Address(final String city, final String country, final boolean hidden) { + super(); + this.city = city; + this.country = country; + this.hidden = hidden; + } + + public String getCity() { + return city; + } + + public void setCity(final String city) { + this.city = city; + } + + public String getCountry() { + return country; + } + + public void setCountry(final String country) { + this.country = country; + } + + @Override + public boolean isHidden() { + return hidden; + } + + public void setHidden(final boolean hidden) { + this.hidden = hidden; + } + +} diff --git a/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/Hidable.java b/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/Hidable.java new file mode 100644 index 0000000000..9eaa0c9619 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/Hidable.java @@ -0,0 +1,9 @@ +package org.baeldung.jackson.dynamicIgnore; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + + +@JsonIgnoreProperties("hidden") +public interface Hidable { + boolean isHidden(); +} diff --git a/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/HidableSerializer.java b/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/HidableSerializer.java new file mode 100644 index 0000000000..35bd8fd7f6 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/HidableSerializer.java @@ -0,0 +1,29 @@ +package org.baeldung.jackson.dynamicIgnore; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +public class HidableSerializer extends JsonSerializer { + + private JsonSerializer defaultSerializer; + + public HidableSerializer(final JsonSerializer serializer) { + defaultSerializer = serializer; + } + + @Override + public void serialize(final Hidable value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { + if (value.isHidden()) + return; + defaultSerializer.serialize(value, jgen, provider); + } + + @Override + public boolean isEmpty(final SerializerProvider provider, final Hidable value) { + return (value == null || value.isHidden()); + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/Person.java b/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/Person.java new file mode 100644 index 0000000000..5fe294a5e1 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/dynamicIgnore/Person.java @@ -0,0 +1,41 @@ +package org.baeldung.jackson.dynamicIgnore; + + +public class Person implements Hidable { + private String name; + private Address address; + private boolean hidden; + + public Person(final String name, final Address address, final boolean hidden) { + super(); + this.name = name; + this.address = address; + this.hidden = hidden; + } + + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public Address getAddress() { + return address; + } + + public void setAddress(final Address address) { + this.address = address; + } + @Override + public boolean isHidden() { + return hidden; + } + + public void setHidden(final boolean hidden) { + this.hidden = hidden; + } + +} 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/jackson/src/test/java/org/baeldung/jackson/test/JacksonDynamicIgnoreTest.java b/jackson/src/test/java/org/baeldung/jackson/test/JacksonDynamicIgnoreTest.java new file mode 100644 index 0000000000..d98f948dec --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/test/JacksonDynamicIgnoreTest.java @@ -0,0 +1,100 @@ +package org.baeldung.jackson.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.baeldung.jackson.dynamicIgnore.Address; +import org.baeldung.jackson.dynamicIgnore.Hidable; +import org.baeldung.jackson.dynamicIgnore.HidableSerializer; +import org.baeldung.jackson.dynamicIgnore.Person; +import org.junit.Before; +import org.junit.Test; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.BeanDescription; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationConfig; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.BeanSerializerModifier; + +public class JacksonDynamicIgnoreTest { + + private ObjectMapper mapper = new ObjectMapper(); + + @Before + public void setUp() { + mapper.setSerializationInclusion(Include.NON_EMPTY); + mapper.registerModule(new SimpleModule() { + @Override + public void setupModule(final SetupContext context) { + super.setupModule(context); + context.addBeanSerializerModifier(new BeanSerializerModifier() { + @Override + public JsonSerializer modifySerializer(final SerializationConfig config, final BeanDescription beanDesc, final JsonSerializer serializer) { + if (Hidable.class.isAssignableFrom(beanDesc.getBeanClass())) { + return new HidableSerializer((JsonSerializer) serializer); + } + return serializer; + } + }); + } + }); + } + + @Test + public void whenNotHidden_thenCorrect() throws JsonProcessingException { + final Address ad = new Address("ny", "usa", false); + final Person person = new Person("john", ad, false); + final String result = mapper.writeValueAsString(person); + + assertTrue(result.contains("name")); + assertTrue(result.contains("john")); + assertTrue(result.contains("address")); + assertTrue(result.contains("usa")); + + System.out.println("Not Hidden = " + result); + } + + @Test + public void whenAddressHidden_thenCorrect() throws JsonProcessingException { + final Address ad = new Address("ny", "usa", true); + final Person person = new Person("john", ad, false); + final String result = mapper.writeValueAsString(person); + + assertTrue(result.contains("name")); + assertTrue(result.contains("john")); + assertFalse(result.contains("address")); + assertFalse(result.contains("usa")); + + System.out.println("Address Hidden = " + result); + } + + @Test + public void whenAllHidden_thenCorrect() throws JsonProcessingException { + final Address ad = new Address("ny", "usa", false); + final Person person = new Person("john", ad, true); + final String result = mapper.writeValueAsString(person); + + assertTrue(result.length() == 0); + + System.out.println("All Hidden = " + result); + } + + @Test + public void whenSerializeList_thenCorrect() throws JsonProcessingException { + final Address ad1 = new Address("tokyo", "jp", true); + final Address ad2 = new Address("london", "uk", false); + final Address ad3 = new Address("ny", "usa", false); + final Person p1 = new Person("john", ad1, false); + final Person p2 = new Person("tom", ad2, true); + final Person p3 = new Person("adam", ad3, false); + + final String result = mapper.writeValueAsString(Arrays.asList(p1, p2, p3)); + + System.out.println(result); + } +} 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/README.md b/mockito-mocks-spring-beans/README.md new file mode 100644 index 0000000000..3ced7161fa --- /dev/null +++ b/mockito-mocks-spring-beans/README.md @@ -0,0 +1,7 @@ +========= + +## Mockito Mocks into Spring Beans + + +### Relevant Articles: +- [Injecting Mockito Mocks into Spring Beans](http://www.baeldung.com/injecting-mocks-in-spring) 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/mockito/README.md b/mockito/README.md index 5ecc5722b0..5e7cd19f78 100644 --- a/mockito/README.md +++ b/mockito/README.md @@ -6,4 +6,5 @@ ### Relevant Articles: - [Mockito Verify Cookbook](http://www.baeldung.com/mockito-verify) - [Mockito When/Then Cookbook](http://www.baeldung.com/mockito-behavior) - +- [Mockito – Using Spies](http://www.baeldung.com/mockito-spy) +- [Mockito – @Mock, @Spy, @Captor and @InjectMocks](http://www.baeldung.com/mockito-annotations) diff --git a/mockito/pom.xml b/mockito/pom.xml index a97a017c5c..a73eea7647 100644 --- a/mockito/pom.xml +++ b/mockito/pom.xml @@ -28,7 +28,7 @@ junit - junit-dep + junit ${junit.version} test @@ -96,19 +96,19 @@ 5.1.35 - 1.7.12 + 1.7.13 1.1.3 5.1.3.Final - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 diff --git a/raml/introduction/0.8/api.raml b/raml/introduction/0.8/api.raml new file mode 100644 index 0000000000..29f769ae16 --- /dev/null +++ b/raml/introduction/0.8/api.raml @@ -0,0 +1,102 @@ +#%RAML 0.8 +title: Baeldung Foo REST Services API +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securitySchemes: + - basicAuth: + description: Each request must contain the headers necessary for + basic authentication + type: Basic Authentication + describedBy: + headers: + Authorization: + description: Used to send the Base64 encoded "username:password" + credentials + type: string + responses: + 401: + description: | + Unauthorized. Either the provided username and password + combination is invalid, or the user is not allowed to access + the content provided by the requested URL. + +schemas: + - foo: !include foo.json + - foos: !include foos.json + - error: !include error.json + +/foos: + get: + description: List all Foos matching query criteria, if provided; + otherwise list all Foos + queryParameters: + name: + type: string + required: false + ownerName: + type: string + required: false + responses: + 200: + body: + application/json: + schema: foos + example: !include foos-example.json + post: + description: Create a new Foo + body: + application/json: + schema: foo + example: foo-example.json + responses: + 201: + body: + application/json: + schema: foo + example: foo-example.json + /{id}: + get: + description: Get a Foo by id + responses: + 200: + body: + application/json: + schema: foo + 404: + body: + application/json: + schema: error + put: + description: Update a Foo by id + body: + application/json: + schema: foo + example: foo-example.json + responses: + 200: + body: + application/json: + schema: foo + 404: + body: + application/json: + schema: error + delete: + description: Delete a Foo by id + responses: + 204: + 404: + body: + application/json: + schema: error + /name/{name}: + get: + description: List all Foos with a certain name + responses: + 200: + body: + application/json: + schema: foos + example: !include foos-example.json \ No newline at end of file diff --git a/raml/introduction/0.8/error-example.json b/raml/introduction/0.8/error-example.json new file mode 100644 index 0000000000..dca56da7c2 --- /dev/null +++ b/raml/introduction/0.8/error-example.json @@ -0,0 +1,4 @@ +{ + "message" : "Not found", + "code" : 1001 +} \ No newline at end of file diff --git a/raml/introduction/0.8/error.json b/raml/introduction/0.8/error.json new file mode 100644 index 0000000000..f6e25b51d2 --- /dev/null +++ b/raml/introduction/0.8/error.json @@ -0,0 +1,12 @@ +{ "$schema": "http://json-schema.org/schema", + "type": "object", + "description": "Error message", + "properties": { + "message": { "type": "string" }, + "code": { "type": integer } + }, + "required": [ + "message", + "code" + ] +} \ No newline at end of file diff --git a/raml/introduction/0.8/foo-example.json b/raml/introduction/0.8/foo-example.json new file mode 100644 index 0000000000..1b1b8c891e --- /dev/null +++ b/raml/introduction/0.8/foo-example.json @@ -0,0 +1,4 @@ +{ + "id" : 1, + "name" : "First Foo" +} \ No newline at end of file diff --git a/raml/introduction/0.8/foo.json b/raml/introduction/0.8/foo.json new file mode 100644 index 0000000000..c024a8c2d3 --- /dev/null +++ b/raml/introduction/0.8/foo.json @@ -0,0 +1,13 @@ +{ "$schema": "http://json-schema.org/schema", + "type": "object", + "description": "Foo details", + "properties": { + "id": { "type": integer }, + "name": { "type": "string" }, + "ownerName": { "type": "string" } + }, + "required": [ + "id", + "name" + ] +} \ No newline at end of file diff --git a/raml/introduction/0.8/foos-example.json b/raml/introduction/0.8/foos-example.json new file mode 100644 index 0000000000..fe9c89d36a --- /dev/null +++ b/raml/introduction/0.8/foos-example.json @@ -0,0 +1,10 @@ +[ + { + "id" : 1, + "name" : "First Foo" + }, + { + "id" : 2, + "name" : "Second Foo" + } +] \ No newline at end of file diff --git a/raml/introduction/0.8/foos.json b/raml/introduction/0.8/foos.json new file mode 100644 index 0000000000..931deab029 --- /dev/null +++ b/raml/introduction/0.8/foos.json @@ -0,0 +1,5 @@ +{ "$schema": "http://json-schema.org/schema", + "type": "array", + "items": { "$ref": "foo" } + "description": "Collection of Foos" +} \ No newline at end of file diff --git a/raml/introduction/1.0/api.raml b/raml/introduction/1.0/api.raml new file mode 100644 index 0000000000..a54d4f11db --- /dev/null +++ b/raml/introduction/1.0/api.raml @@ -0,0 +1,101 @@ +#%RAML 1.0 +title: Baeldung Foo REST Services API +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: basicAuth +securitySchemes: + - basicAuth: + description: Each request must contain the headers necessary for + basic authentication + type: Basic Authentication + describedBy: + headers: + Authorization: + description: Used to send the Base64 encoded "username:password" + credentials + type: string + responses: + 401: + description: | + Unauthorized. Either the provided username and password + combination is invalid, or the user is not allowed to access + the content provided by the requested URL. +types: + Foo: !include types/Foo.raml + Error: !include types/Error.raml +/foos: + get: + description: List all Foos matching query criteria, if provided; + otherwise list all Foos + queryParameters: + name?: string + ownerName?: string + responses: + 200: + body: + application/json: + type: Foo[] + example: !include examples/Foos.json + post: + description: Create a new Foo + body: + application/json: + type: Foo + example: !include examples/Foo.json + responses: + 201: + body: + application/json: + type: Foo + example: !include examples/Foo.json + /{id}: + get: + description: Get a Foo by id + responses: + 200: + body: + application/json: + type: Foo + example: !include examples/Foo.json + 404: + body: + application/json: + type: Error + example: !include examples/Error.json + put: + description: Update a Foo by id + body: + application/json: + type: Foo + example: !include examples/Foo.json + responses: + 200: + body: + application/json: + type: Foo + example: !include examples/Foo.json + 404: + body: + application/json: + type: Error + example: !include examples/Error.json + delete: + description: Delete a Foo by id + responses: + 204: + 404: + body: + application/json: + type: Error + example: !include examples/Error.json + /name/{name}: + get: + description: List all Foos with a certain name + responses: + 200: + body: + application/json: + type: Foo[] + example: !include examples/Foos.json \ No newline at end of file diff --git a/raml/introduction/1.0/examples/Error.json b/raml/introduction/1.0/examples/Error.json new file mode 100644 index 0000000000..dca56da7c2 --- /dev/null +++ b/raml/introduction/1.0/examples/Error.json @@ -0,0 +1,4 @@ +{ + "message" : "Not found", + "code" : 1001 +} \ No newline at end of file diff --git a/raml/introduction/1.0/examples/Foo.json b/raml/introduction/1.0/examples/Foo.json new file mode 100644 index 0000000000..1b1b8c891e --- /dev/null +++ b/raml/introduction/1.0/examples/Foo.json @@ -0,0 +1,4 @@ +{ + "id" : 1, + "name" : "First Foo" +} \ No newline at end of file diff --git a/raml/introduction/1.0/examples/Foos.json b/raml/introduction/1.0/examples/Foos.json new file mode 100644 index 0000000000..fe9c89d36a --- /dev/null +++ b/raml/introduction/1.0/examples/Foos.json @@ -0,0 +1,10 @@ +[ + { + "id" : 1, + "name" : "First Foo" + }, + { + "id" : 2, + "name" : "Second Foo" + } +] \ No newline at end of file diff --git a/raml/introduction/1.0/types/Error.raml b/raml/introduction/1.0/types/Error.raml new file mode 100644 index 0000000000..8d54b5f181 --- /dev/null +++ b/raml/introduction/1.0/types/Error.raml @@ -0,0 +1,5 @@ +#%RAML 1.0 DataType + + properties: + code: integer + message: string diff --git a/raml/introduction/1.0/types/Foo.raml b/raml/introduction/1.0/types/Foo.raml new file mode 100644 index 0000000000..1702865e05 --- /dev/null +++ b/raml/introduction/1.0/types/Foo.raml @@ -0,0 +1,6 @@ +#%RAML 1.0 DataType + +properties: + id: integer + name: string + ownerName?: string diff --git a/raml/modularization/api-before-modularization.raml b/raml/modularization/api-before-modularization.raml new file mode 100644 index 0000000000..b580c33983 --- /dev/null +++ b/raml/modularization/api-before-modularization.raml @@ -0,0 +1,119 @@ +#%RAML 1.0 +title: API for REST Services used in the RAML tutorials on Baeldung.com +documentation: + - title: Overview + - content: | + This document defines the interface for the REST services + used in the popular RAML Tutorial series at Baeldung.com. + - title: Disclaimer: + - content: | + All names used in this definition are purely fictional. + Any similarities between the names used in this tutorial and those of real persons, whether living or dead, are merely coincidental. + - title: Copyright + - content: Copyright 2016 by Baeldung.com. All rights reserved. +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: basicAuth +securitySchemes: + - basicAuth: + description: Each request must contain the headers necessary for + basic authentication + type: Basic Authentication + describedBy: + headers: + Authorization: + description: | + Used to send the Base64 encoded "username:password" + credentials + type: string + responses: + 401: + description: | + Unauthorized. Either the provided username and password + combination is invalid, or the user is not allowed to + access the content provided by the requested URL. +types: + Foo: !include types/Foo.raml + Bar: !include types/Bar.raml + Error: !include types/Error.raml +resourceTypes: + - collection: + usage: Use this resourceType to represent a collection of items + description: A collection of <> + get: + description: | + Get all <>, + optionally filtered + is: [ hasResponseCollection ] + post: + description: | + Create a new <> + is: [ hasRequestItem ] + - item: + usage: Use this resourceType to represent any single item + description: A single <> + get: + description: Get a <> by <> + is: [ hasResponseItem, hasNotFound ] + put: + description: Update a <> by <> + is: [ hasRequestItem, hasResponseItem, hasNotFound ] + delete: + description: Delete a <> by <> + is: [ hasNotFound ] + responses: + 204: +traits: + - hasRequestItem: + body: + application/json: + type: <> + - hasResponseItem: + responses: + 200: + body: + application/json: + type: <> + example: !include examples/<>.json + - hasResponseCollection: + responses: + 200: + body: + application/json: + type: <>[] + example: !include examples/<>.json + - hasNotFound: + responses: + 404: + body: + application/json: + type: Error + example: !include examples/Error.json +/foos: + type: collection + typeName: Foo + get: + queryParameters: + name?: string + ownerName?: string + /{fooId}: + type: item + typeName: Foo + /name/{name}: + get: + description: List all foos with a certain name + typeName: Foo + is: [ hasResponseCollection ] +/bars: + type: collection + typeName: Bar + /{barId}: + type: item + typeName: Bar + /fooId/{fooId}: + get: + description: Get all bars for the matching fooId + typeName: Bar + is: [ hasResponseCollection ] \ No newline at end of file diff --git a/raml/modularization/api-with-libraries.raml b/raml/modularization/api-with-libraries.raml new file mode 100644 index 0000000000..b3081e843a --- /dev/null +++ b/raml/modularization/api-with-libraries.raml @@ -0,0 +1,50 @@ +#%RAML 1.0 +title: API for REST Services used in the RAML tutorials on Baeldung.com +documentation: + - title: Overview + - content: | + This document defines the interface for the REST services + used in the popular RAML Tutorial series at Baeldung.com. + - title: Disclaimer: + - content: | + All names used in this definition are purely fictional. + Any similarities between the names used in this tutorial and those of real persons, whether living or dead, are merely coincidental. + - title: Copyright + - content: Copyright 2016 by Baeldung.com. All rights reserved. +uses: + mySecuritySchemes: !include libraries/security.raml + myDataTypes: !include libraries/dataTypes.raml + myResourceTypes: !include libraries/resourceTypes.raml + myTraits: !include libraries/traits.raml +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: [ mySecuritySchemes.basicAuth ] +/foos: + type: myResourceTypes.collection + typeName: myDataTypes.Foo + get: + queryParameters: + name?: string + ownerName?: string + /{fooId}: + type: myResourceTypes.item + typeName: myDataTypes.Foo + /name/{name}: + get: + description: List all foos with a certain name + typeName: myDataTypes.Foo + is: [ myTraits.hasResponseCollection ] +/bars: + type: myResourceTypes.collection + typeName: myDataTypes.Bar + /{barId}: + type: myResourceTypes.item + typeName: myDataTypes.Bar + /fooId/{fooId}: + get: + description: Get all bars for the matching fooId + type: myResourceTypes.item + typeName: myDataTypes.Bar + is: [ myTraits.hasResponseCollection ] \ No newline at end of file diff --git a/raml/modularization/api-with-typed-fragments.raml b/raml/modularization/api-with-typed-fragments.raml new file mode 100644 index 0000000000..2bb4e317c1 --- /dev/null +++ b/raml/modularization/api-with-typed-fragments.raml @@ -0,0 +1,74 @@ +#%RAML 1.0 +title: API for REST Services used in the RAML tutorials on Baeldung.com +documentation: + - title: Overview + - content: | + This document defines the interface for the REST services + used in the popular RAML Tutorial series at Baeldung.com. + - title: Disclaimer: + - content: | + All names used in this definition are purely fictional. + Any similarities between the names used in this tutorial and those of real persons, whether living or dead, are merely coincidental. + - title: Copyright + - content: Copyright 2016 by Baeldung.com. All rights reserved. +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: [ basicAuth ] +securitySchemes: + - basicAuth: + description: Each request must contain the headers necessary for + basic authentication + type: Basic Authentication + describedBy: + headers: + Authorization: + description: | + Used to send the Base64 encoded "username:password" + credentials + type: string + responses: + 401: + description: | + Unauthorized. Either the provided username and password + combination is invalid, or the user is not allowed to + access the content provided by the requested URL. +types: + Foo: !include types/Foo.raml + Bar: !include types/Bar.raml + Error: !include types/Error.raml +resourceTypes: + - collection: !include resourceTypes/collection.raml + - item: !include resourceTypes/item.raml +traits: + - hasRequestItem: !include traits/hasRequestItem.raml + - hasResponseItem: !include traits/hasResponseItem.raml + - hasResponseCollection: !include traits/hasResponseCollection.raml + - hasNotFound: !include traits/hasNotFound.raml +/foos: + type: collection + typeName: Foo + get: + queryParameters: + name?: string + ownerName?: string + /{fooId}: + type: item + typeName: Foo + /name/{name}: + get: + description: List all foos with a certain name + typeName: Foo + is: [ hasResponseCollection ] +/bars: + type: collection + typeName: Bar + /{barId}: + type: item + typeName: Bar + /fooId/{fooId}: + get: + description: Get all bars for the matching fooId + typeName: Bar + is: [ hasResponseCollection ] \ No newline at end of file diff --git a/raml/modularization/api.raml b/raml/modularization/api.raml new file mode 100644 index 0000000000..184027cd26 --- /dev/null +++ b/raml/modularization/api.raml @@ -0,0 +1,47 @@ +#%RAML 1.0 +title: Baeldung Foo REST Services API +uses: + security: !include libraries/security.raml +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: [ security.basicAuth ] +types: + Foo: !include types/Foo.raml + Bar: !include types/Bar.raml + Error: !include types/Error.raml +resourceTypes: + - collection: !include resourceTypes/collection.raml + - item: !include resourceTypes/item.raml +traits: + - hasRequestItem: !include traits/hasRequestItem.raml + - hasResponseItem: !include traits/hasResponseItem.raml + - hasResponseCollection: !include traits/hasResponseCollection.raml + - hasNotFound: !include traits/hasNotFound.raml +/foos: + type: collection + typeName: Foo + get: + queryParameters: + name?: string + ownerName?: string + /{fooId}: + type: item + typeName: Foo + /name/{name}: + get: + description: List all foos with a certain name + typeName: Foo + is: [ hasResponseCollection ] +/bars: + type: collection + typeName: Bar + /{barId}: + type: item + typeName: Bar + /fooId/{fooId}: + get: + description: Get all bars for the matching fooId + typeName: Bar + is: [ hasResponseCollection ] \ No newline at end of file diff --git a/raml/modularization/examples/Bar.json b/raml/modularization/examples/Bar.json new file mode 100644 index 0000000000..0ee1b34edb --- /dev/null +++ b/raml/modularization/examples/Bar.json @@ -0,0 +1,6 @@ +{ + "id" : 1, + "name" : "First Bar", + "city" : "Austin", + "fooId" : 2 +} \ No newline at end of file diff --git a/raml/modularization/examples/Bars.json b/raml/modularization/examples/Bars.json new file mode 100644 index 0000000000..89ea875432 --- /dev/null +++ b/raml/modularization/examples/Bars.json @@ -0,0 +1,19 @@ +[ + { + "id" : 1, + "name" : "First Bar", + "city" : "Austin", + "fooId" : 2 + }, + { + "id" : 2, + "name" : "Second Bar", + "city" : "Dallas", + "fooId" : 1 + }, + { + "id" : 3, + "name" : "Third Bar", + "fooId" : 2 + } +] \ No newline at end of file diff --git a/raml/modularization/examples/Error.json b/raml/modularization/examples/Error.json new file mode 100644 index 0000000000..dca56da7c2 --- /dev/null +++ b/raml/modularization/examples/Error.json @@ -0,0 +1,4 @@ +{ + "message" : "Not found", + "code" : 1001 +} \ No newline at end of file diff --git a/raml/modularization/examples/Foo.json b/raml/modularization/examples/Foo.json new file mode 100644 index 0000000000..1b1b8c891e --- /dev/null +++ b/raml/modularization/examples/Foo.json @@ -0,0 +1,4 @@ +{ + "id" : 1, + "name" : "First Foo" +} \ No newline at end of file diff --git a/raml/modularization/examples/Foos.json b/raml/modularization/examples/Foos.json new file mode 100644 index 0000000000..74f64689f0 --- /dev/null +++ b/raml/modularization/examples/Foos.json @@ -0,0 +1,16 @@ +[ + { + "id" : 1, + "name" : "First Foo", + "ownerName" : "Jack Robinson" + }, + { + "id" : 2, + "name" : "Second Foo" + }, + { + "id" : 3, + "name" : "Third Foo", + "ownerName" : "Chuck Norris" + } +] \ No newline at end of file diff --git a/raml/modularization/extensions/en_US/additionalResources.raml b/raml/modularization/extensions/en_US/additionalResources.raml new file mode 100644 index 0000000000..20c6851f23 --- /dev/null +++ b/raml/modularization/extensions/en_US/additionalResources.raml @@ -0,0 +1,16 @@ +#%RAML 1.0 Extension +# File located at: +# /extensions/en_US/additionalResources.raml +masterRef: /api.raml +usage: This extension defines additional resources for version 2 of the API. +version: v2 +/foos: + /bar/{barId}: + get: + description: | + Get the foo that is related to the bar having barId = {barId} + typeName: Foo + queryParameters: + barId?: integer + typeName: Foo + is: [ hasResponseItem ] diff --git a/raml/modularization/libraries/dataTypes.raml b/raml/modularization/libraries/dataTypes.raml new file mode 100644 index 0000000000..8a240e62dc --- /dev/null +++ b/raml/modularization/libraries/dataTypes.raml @@ -0,0 +1,19 @@ +#%RAML 1.0 Library +# This is the file /libraries/dataTypes.raml +usage: This library defines the data types for the API +types: + Foo: + properties: + id: integer + name: string + ownerName?: string + Bar: + properties: + id: integer + name: string + city?: string + fooId: integer + Error: + properties: + code: integer + message: string diff --git a/raml/modularization/libraries/resourceTypes.raml b/raml/modularization/libraries/resourceTypes.raml new file mode 100644 index 0000000000..681ff710d6 --- /dev/null +++ b/raml/modularization/libraries/resourceTypes.raml @@ -0,0 +1,32 @@ +#%RAML 1.0 Library +# This is the file /libraries/resourceTypes.raml +usage: This library defines the resource types for the API +uses: + myTraits: !include traits.raml +resourceTypes: + collection: + usage: Use this resourceType to represent a collection of items + description: A collection of <> + get: + description: | + Get all <>, + optionally filtered + is: [ myTraits.hasResponseCollection ] + post: + description: | + Create a new <> + is: [ myTraits.hasRequestItem ] + item: + usage: Use this resourceType to represent any single item + description: A single <> + get: + description: Get a <> by <> + is: [ myTraits.hasResponseItem, myTraits.hasNotFound ] + put: + description: Update a <> by <> + is: [ myTraits.hasRequestItem, myTraits.hasResponseItem, myTraits.hasNotFound ] + delete: + description: Delete a <> by <> + is: [ myTraits.hasNotFound ] + responses: + 204: diff --git a/raml/modularization/libraries/securitySchemes.raml b/raml/modularization/libraries/securitySchemes.raml new file mode 100644 index 0000000000..621c6ac975 --- /dev/null +++ b/raml/modularization/libraries/securitySchemes.raml @@ -0,0 +1,20 @@ +#%RAML 1.0 Library +# This is the file /libraries/securitySchemes.raml +securitySchemes: + - basicAuth: + description: Each request must contain the headers necessary for + basic authentication + type: Basic Authentication + describedBy: + headers: + Authorization: + description: | + Used to send the Base64 encoded "username:password" + credentials + type: string + responses: + 401: + description: | + Unauthorized. Either the provided username and password + combination is invalid, or the user is not allowed to + access the content provided by the requested URL. diff --git a/raml/modularization/libraries/traits.raml b/raml/modularization/libraries/traits.raml new file mode 100644 index 0000000000..c101d94c02 --- /dev/null +++ b/raml/modularization/libraries/traits.raml @@ -0,0 +1,33 @@ +#%RAML 1.0 Library +# This is the file /libraries/traits.raml +usage: This library defines some basic traits +traits: + hasRequestItem: + usage: Use this trait for resources whose request body is a single item + body: + application/json: + type: <> + hasResponseItem: + usage: Use this trait for resources whose response body is a single item + responses: + 200: + body: + application/json: + type: <> + example: !include /examples/<>.json + hasResponseCollection: + usage: Use this trait for resources whose response body is a collection of items + responses: + 200: + body: + application/json: + type: <>[] + example: !include /examples/<>.json + hasNotFound: + usage: Use this trait for resources that could respond with a 404 status + responses: + 404: + body: + application/json: + type: Error + example: !include /examples/Error.json diff --git a/raml/modularization/overlays/es_ES/additionalResources.raml b/raml/modularization/overlays/es_ES/additionalResources.raml new file mode 100644 index 0000000000..e8748fd726 --- /dev/null +++ b/raml/modularization/overlays/es_ES/additionalResources.raml @@ -0,0 +1,13 @@ +#%RAML 1.0 Overlay +# Archivo situado en: +# /overlays/es_ES/additionalResources.raml +masterRef: /api.raml +usage: | + Se trata de un espaΓ±ol demasiado que describe los recursos adicionales + para la versiΓ³n 2 del API. +version: v2 +/foos: + /bar/{barId}: + get: + description: | + Obtener el foo que se relaciona con el bar tomando barId = {barId} diff --git a/raml/modularization/overlays/es_ES/documentationItems.raml b/raml/modularization/overlays/es_ES/documentationItems.raml new file mode 100644 index 0000000000..dc6ca3eaef --- /dev/null +++ b/raml/modularization/overlays/es_ES/documentationItems.raml @@ -0,0 +1,23 @@ +#%RAML 1.0 Overlay +# File located at (archivo situado en): +# /overlays/es_ES/documentationItems.raml +masterRef: /api.raml +usage: | + To provide user documentation and other descriptive text in Spanish + (Para proporcionar la documentaciΓ³n del usuario y otro texto descriptivo en espaΓ±ol) +title: API para servicios REST utilizados en los tutoriales RAML en Baeldung.com +documentation: + - title: DescripciΓ³n general + - content: | + Este documento define la interfaz para los servicios REST + utilizados en la popular serie de RAML Tutorial en Baeldung.com + - title: Renuncia + - content: | + Todos los nombres usados ​​en esta definiciΓ³n son pura ficciΓ³n. + Cualquier similitud entre los nombres utilizados en este tutorial + y los de las personas reales, ya sea vivo o muerto, + no son mΓ‘s que coincidenta. + + - title: Derechos de autor + - content: | + Derechos de autor 2016 por Baeldung.com. Todos los derechos reservados. diff --git a/raml/modularization/resourceTypes/collection.raml b/raml/modularization/resourceTypes/collection.raml new file mode 100644 index 0000000000..0cab417f14 --- /dev/null +++ b/raml/modularization/resourceTypes/collection.raml @@ -0,0 +1,12 @@ +#%RAML 1.0 ResourceType +usage: Use this resourceType to represent a collection of items +description: A collection of <> +get: + description: | + Get all <>, + optionally filtered + is: [ hasResponseCollection ] +post: + description: | + Create a new <> + is: [ hasRequestItem ] diff --git a/raml/modularization/resourceTypes/item.raml b/raml/modularization/resourceTypes/item.raml new file mode 100644 index 0000000000..59f057ca98 --- /dev/null +++ b/raml/modularization/resourceTypes/item.raml @@ -0,0 +1,14 @@ +#%RAML 1.0 ResourceType +usage: Use this resourceType to represent any single item +description: A single <> +get: + description: Get a <> by <> + is: [ hasResponseItem, hasNotFound ] +put: + description: Update a <> by <> + is: [ hasRequestItem, hasResponseItem, hasNotFound ] +delete: + description: Delete a <> by <> + is: [ hasNotFound ] + responses: + 204: diff --git a/raml/modularization/traits/hasNotFound.raml b/raml/modularization/traits/hasNotFound.raml new file mode 100644 index 0000000000..8d2d940c03 --- /dev/null +++ b/raml/modularization/traits/hasNotFound.raml @@ -0,0 +1,8 @@ +#%RAML 1.0 Trait +usage: Use this trait for resources that could respond with a 404 status +responses: + 404: + body: + application/json: + type: Error + example: !include /examples/Error.json diff --git a/raml/modularization/traits/hasRequestItem.raml b/raml/modularization/traits/hasRequestItem.raml new file mode 100644 index 0000000000..06281781c0 --- /dev/null +++ b/raml/modularization/traits/hasRequestItem.raml @@ -0,0 +1,5 @@ +#%RAML 1.0 Trait +usage: Use this trait for resources whose request body is a single item +body: + application/json: + type: <> diff --git a/raml/modularization/traits/hasResponseCollection.raml b/raml/modularization/traits/hasResponseCollection.raml new file mode 100644 index 0000000000..47dc1c2d5f --- /dev/null +++ b/raml/modularization/traits/hasResponseCollection.raml @@ -0,0 +1,8 @@ +#%RAML 1.0 Trait +usage: Use this trait for resources whose response body is a collection of items +responses: + 200: + body: + application/json: + type: <>[] + example: !include /examples/<>.json diff --git a/raml/modularization/traits/hasResponseItem.raml b/raml/modularization/traits/hasResponseItem.raml new file mode 100644 index 0000000000..94d3ba0756 --- /dev/null +++ b/raml/modularization/traits/hasResponseItem.raml @@ -0,0 +1,8 @@ +#%RAML 1.0 Trait +usage: Use this trait for resources whose response body is a single item +responses: + 200: + body: + application/json: + type: <> + example: !include /examples/<>.json diff --git a/raml/modularization/types/Bar.raml b/raml/modularization/types/Bar.raml new file mode 100644 index 0000000000..92255a75fe --- /dev/null +++ b/raml/modularization/types/Bar.raml @@ -0,0 +1,7 @@ +#%RAML 1.0 DataType + +properties: + id: integer + name: string + city?: string + fooId: integer diff --git a/raml/modularization/types/Error.raml b/raml/modularization/types/Error.raml new file mode 100644 index 0000000000..8d54b5f181 --- /dev/null +++ b/raml/modularization/types/Error.raml @@ -0,0 +1,5 @@ +#%RAML 1.0 DataType + + properties: + code: integer + message: string diff --git a/raml/modularization/types/Foo.raml b/raml/modularization/types/Foo.raml new file mode 100644 index 0000000000..1702865e05 --- /dev/null +++ b/raml/modularization/types/Foo.raml @@ -0,0 +1,6 @@ +#%RAML 1.0 DataType + +properties: + id: integer + name: string + ownerName?: string diff --git a/raml/resource-types-and-traits/api-before-resource-types-and-traits.raml b/raml/resource-types-and-traits/api-before-resource-types-and-traits.raml new file mode 100644 index 0000000000..652a3d10f7 --- /dev/null +++ b/raml/resource-types-and-traits/api-before-resource-types-and-traits.raml @@ -0,0 +1,177 @@ +#%RAML 1.0 +title: Baeldung Foo REST Services API +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: basicAuth +securitySchemes: + - basicAuth: + description: Each request must contain the headers necessary for + basic authentication + type: Basic Authentication + describedBy: + headers: + Authorization: + description: Used to send the Base64 encoded "username:password" + credentials + type: string + responses: + 401: + description: | + Unauthorized. Either the provided username and password + combination is invalid, or the user is not allowed to access + the content provided by the requested URL. +types: + Foo: !include types/Foo.raml + Bar: !include types/Bar.raml + Error: !include types/Error.raml +traits: +/foos: + get: + description: List all foos matching query criteria, if provided; + otherwise list all foos + queryParameters: + name?: string + ownerName?: string + responses: + 200: + body: + application/json: + type: Foo[] + example: !include examples/Foos.json + post: + description: Create a new foo + body: + application/json: + type: Foo + example: !include examples/Foo.json + responses: + 201: + body: + application/json: + type: Foo + example: !include examples/Foo.json + /{fooId}: + get: + description: Get a foo by fooId + responses: + 200: + body: + application/json: + type: Foo + example: !include examples/Foo.json + 404: + body: + application/json: + type: Error + example: !include examples/Error.json + put: + description: Update a foo by fooId + body: + application/json: + type: Foo + example: !include examples/Foo.json + responses: + 200: + body: + application/json: + type: Foo + example: !include examples/Foo.json + 404: + body: + application/json: + type: Error + example: !include examples/Error.json + delete: + description: Delete a foo by fooId + responses: + 204: + 404: + body: + application/json: + type: Error + example: !include examples/Error.json + /name/{name}: + get: + description: List all foos with a certain name + responses: + 200: + body: + application/json: + type: Foo[] + example: !include examples/Foos.json +/bars: + get: + description: List all bars matching query criteria, if provided; + otherwise list all bars + queryParameters: + name?: string + ownerName?: string + responses: + 200: + body: + application/json: + type: Bar[] + example: !include examples/Bars.json + post: + description: Create a new bar + body: + application/json: + type: Bar + example: !include examples/Bar.json + responses: + 201: + body: + application/json: + type: Bar + example: !include examples/Bar.json + /{barId}: + get: + description: Get a bar by barId + responses: + 200: + body: + application/json: + type: Bar + example: !include examples/Bar.json + 404: + body: + application/json: + type: Error + example: !include examples/Error.json + put: + description: Update a bar by barId + body: + application/json: + type: Bar + example: !include examples/Bar.json + responses: + 200: + body: + application/json: + type: Bar + example: !include examples/Bar.json + 404: + body: + application/json: + type: Error + example: !include examples/Error.json + delete: + description: Delete a bar by barId + responses: + 204: + 404: + body: + application/json: + type: Error + example: !include examples/Error.json + /fooId/{fooId}: + get: + description: Get all bars for the matching fooId + responses: + 200: + body: + application/json: + type: Bar[] + example: !include examples/Bars.json \ No newline at end of file diff --git a/raml/resource-types-and-traits/api.raml b/raml/resource-types-and-traits/api.raml new file mode 100644 index 0000000000..c07f0cba28 --- /dev/null +++ b/raml/resource-types-and-traits/api.raml @@ -0,0 +1,108 @@ +#%RAML 1.0 +title: Baeldung Foo REST Services API +version: v1 +protocols: [ HTTPS ] +baseUri: http://rest-api.baeldung.com/api/{version} +mediaType: application/json +securedBy: basicAuth +securitySchemes: + - basicAuth: + description: Each request must contain the headers necessary for + basic authentication + type: Basic Authentication + describedBy: + headers: + Authorization: + description: | + Used to send the Base64 encoded "username:password" + credentials + type: string + responses: + 401: + description: | + Unauthorized. Either the provided username and password + combination is invalid, or the user is not allowed to + access the content provided by the requested URL. +types: + Foo: !include types/Foo.raml + Bar: !include types/Bar.raml + Error: !include types/Error.raml +resourceTypes: + - collection: + usage: Use this resourceType to represent a collection of items + description: A collection of <> + get: + description: | + Get all <>, + optionally filtered + is: [ hasResponseCollection ] + post: + description: | + Create a new <> + is: [ hasRequestItem ] + - item: + usage: Use this resourceType to represent any single item + description: A single <> + get: + description: Get a <> by <> + is: [ hasResponseItem, hasNotFound ] + put: + description: Update a <> by <> + is: [ hasRequestItem, hasResponseItem, hasNotFound ] + delete: + description: Delete a <> by <> + is: [ hasNotFound ] + responses: + 204: +traits: + - hasRequestItem: + body: + application/json: + type: <> + - hasResponseItem: + responses: + 200: + body: + application/json: + type: <> + example: !include examples/<>.json + - hasResponseCollection: + responses: + 200: + body: + application/json: + type: <>[] + example: !include examples/<>.json + - hasNotFound: + responses: + 404: + body: + application/json: + type: Error + example: !include examples/Error.json +/foos: + type: collection + typeName: Foo + get: + queryParameters: + name?: string + ownerName?: string + /{fooId}: + type: item + typeName: Foo + /name/{name}: + get: + description: List all foos with a certain name + typeName: Foo + is: [ hasResponseCollection ] +/bars: + type: collection + typeName: Bar + /{barId}: + type: item + typeName: Bar + /fooId/{fooId}: + get: + description: Get all bars for the matching fooId + typeName: Bar + is: [ hasResponseCollection ] \ No newline at end of file diff --git a/raml/resource-types-and-traits/examples/Bar.json b/raml/resource-types-and-traits/examples/Bar.json new file mode 100644 index 0000000000..0ee1b34edb --- /dev/null +++ b/raml/resource-types-and-traits/examples/Bar.json @@ -0,0 +1,6 @@ +{ + "id" : 1, + "name" : "First Bar", + "city" : "Austin", + "fooId" : 2 +} \ No newline at end of file diff --git a/raml/resource-types-and-traits/examples/Bars.json b/raml/resource-types-and-traits/examples/Bars.json new file mode 100644 index 0000000000..89ea875432 --- /dev/null +++ b/raml/resource-types-and-traits/examples/Bars.json @@ -0,0 +1,19 @@ +[ + { + "id" : 1, + "name" : "First Bar", + "city" : "Austin", + "fooId" : 2 + }, + { + "id" : 2, + "name" : "Second Bar", + "city" : "Dallas", + "fooId" : 1 + }, + { + "id" : 3, + "name" : "Third Bar", + "fooId" : 2 + } +] \ No newline at end of file diff --git a/raml/resource-types-and-traits/examples/Error.json b/raml/resource-types-and-traits/examples/Error.json new file mode 100644 index 0000000000..dca56da7c2 --- /dev/null +++ b/raml/resource-types-and-traits/examples/Error.json @@ -0,0 +1,4 @@ +{ + "message" : "Not found", + "code" : 1001 +} \ No newline at end of file diff --git a/raml/resource-types-and-traits/examples/Foo.json b/raml/resource-types-and-traits/examples/Foo.json new file mode 100644 index 0000000000..1b1b8c891e --- /dev/null +++ b/raml/resource-types-and-traits/examples/Foo.json @@ -0,0 +1,4 @@ +{ + "id" : 1, + "name" : "First Foo" +} \ No newline at end of file diff --git a/raml/resource-types-and-traits/examples/Foos.json b/raml/resource-types-and-traits/examples/Foos.json new file mode 100644 index 0000000000..74f64689f0 --- /dev/null +++ b/raml/resource-types-and-traits/examples/Foos.json @@ -0,0 +1,16 @@ +[ + { + "id" : 1, + "name" : "First Foo", + "ownerName" : "Jack Robinson" + }, + { + "id" : 2, + "name" : "Second Foo" + }, + { + "id" : 3, + "name" : "Third Foo", + "ownerName" : "Chuck Norris" + } +] \ No newline at end of file diff --git a/raml/resource-types-and-traits/types/Bar.raml b/raml/resource-types-and-traits/types/Bar.raml new file mode 100644 index 0000000000..92255a75fe --- /dev/null +++ b/raml/resource-types-and-traits/types/Bar.raml @@ -0,0 +1,7 @@ +#%RAML 1.0 DataType + +properties: + id: integer + name: string + city?: string + fooId: integer diff --git a/raml/resource-types-and-traits/types/Error.raml b/raml/resource-types-and-traits/types/Error.raml new file mode 100644 index 0000000000..8d54b5f181 --- /dev/null +++ b/raml/resource-types-and-traits/types/Error.raml @@ -0,0 +1,5 @@ +#%RAML 1.0 DataType + + properties: + code: integer + message: string diff --git a/raml/resource-types-and-traits/types/Foo.raml b/raml/resource-types-and-traits/types/Foo.raml new file mode 100644 index 0000000000..1702865e05 --- /dev/null +++ b/raml/resource-types-and-traits/types/Foo.raml @@ -0,0 +1,6 @@ +#%RAML 1.0 DataType + +properties: + id: integer + name: string + ownerName?: string diff --git a/rest-testing/pom.xml b/rest-testing/pom.xml index 488a8a3cdb..b8fdc50a01 100644 --- a/rest-testing/pom.xml +++ b/rest-testing/pom.xml @@ -78,7 +78,7 @@ junit - junit-dep + junit ${junit.version} test @@ -141,22 +141,22 @@ 4.1.5.RELEASE - 2.4.4 + 2.5.5 - 1.7.12 + 1.7.13 1.1.3 5.1.3.Final - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 diff --git a/sandbox/pom.xml b/sandbox/pom.xml index 55cb9f11f2..95b2df2cb3 100644 --- a/sandbox/pom.xml +++ b/sandbox/pom.xml @@ -73,7 +73,7 @@ junit - junit-dep + junit ${junit.version} test @@ -141,10 +141,10 @@ 5.1.35 - 2.4.4 + 2.5.5 - 1.7.12 + 1.7.13 1.1.3 @@ -156,7 +156,7 @@ 1.3 - 4.11 + 4.12 1.10.19 4.4.1 diff --git a/spring-all/.settings/org.eclipse.wst.common.project.facet.core.xml b/spring-all/.settings/org.eclipse.wst.common.project.facet.core.xml index 9ca0d1c1b7..991897a4ac 100644 --- a/spring-all/.settings/org.eclipse.wst.common.project.facet.core.xml +++ b/spring-all/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -1,6 +1,6 @@ - + diff --git a/spring-all/README.md b/spring-all/README.md index 4a3bd25077..977b8b7357 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -6,4 +6,6 @@ This project is used to replicate Spring Exceptions only. ### Relevant articles: -- [Properties with Spring](http://www.baeldung.com/2012/02/06/properties-with-spring) - checkout the `org.baeldung.properties` package for all scenarios of properties injection and usage \ No newline at end of file +- [Properties with Spring](http://www.baeldung.com/2012/02/06/properties-with-spring) - checkout the `org.baeldung.properties` package for all scenarios of properties injection and usage +- [Spring Profiles](http://www.baeldung.com/spring-profiles) +- [A Spring Custom Annotation for a Better DAO](http://www.baeldung.com/spring-annotation-bean-pre-processor) diff --git a/spring-all/pom.xml b/spring-all/pom.xml index 0551abe5a5..6ce8ad7196 100644 --- a/spring-all/pom.xml +++ b/spring-all/pom.xml @@ -127,8 +127,7 @@ junit - junit-dep - ${junit.version} + junit test @@ -164,7 +163,6 @@ org.apache.maven.plugins maven-compiler-plugin - ${maven-compiler-plugin.version} 1.8 1.8 @@ -174,7 +172,6 @@ org.apache.maven.plugins maven-war-plugin - ${maven-war-plugin.version} false @@ -183,7 +180,6 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven-surefire-plugin.version} @@ -221,29 +217,29 @@ - 4.2.2.RELEASE - 4.0.2.RELEASE + 4.2.4.RELEASE + 4.0.3.RELEASE 3.20.0-GA 1.2 4.3.11.Final - 5.1.36 + 5.1.37 - 1.7.12 + 1.7.13 1.1.3 - 5.2.1.Final + 5.2.2.Final - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 diff --git a/spring-all/src/main/java/org/baeldung/caching/config/CachingConfig.java b/spring-all/src/main/java/org/baeldung/caching/config/CachingConfig.java new file mode 100644 index 0000000000..4153ec9636 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/caching/config/CachingConfig.java @@ -0,0 +1,29 @@ +package org.baeldung.caching.config; + +import java.util.Arrays; + +import org.baeldung.caching.example.CustomerDataService; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.concurrent.ConcurrentMapCache; +import org.springframework.cache.support.SimpleCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableCaching +public class CachingConfig { + + @Bean + public CustomerDataService customerDataService() { + return new CustomerDataService(); + } + + @Bean + public CacheManager cacheManager() { + final SimpleCacheManager cacheManager = new SimpleCacheManager(); + cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("directory"), new ConcurrentMapCache("addresses"))); + return cacheManager; + } + +} diff --git a/spring-all/src/main/java/org/baeldung/caching/config/MyAppConfig.java b/spring-all/src/main/java/org/baeldung/caching/config/MyAppConfig.java deleted file mode 100644 index 467e50c15e..0000000000 --- a/spring-all/src/main/java/org/baeldung/caching/config/MyAppConfig.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.baeldung.caching.config; - -import org.springframework.cache.annotation.EnableCaching; -import org.springframework.context.annotation.Configuration; - -@Configuration -@EnableCaching -public class MyAppConfig { - // Your configuration code goes here. -} diff --git a/spring-all/src/main/java/org/baeldung/caching/example/CustomerDataService.java b/spring-all/src/main/java/org/baeldung/caching/example/CustomerDataService.java index 86026de93a..fe4de5d282 100644 --- a/spring-all/src/main/java/org/baeldung/caching/example/CustomerDataService.java +++ b/spring-all/src/main/java/org/baeldung/caching/example/CustomerDataService.java @@ -10,12 +10,18 @@ import org.springframework.cache.annotation.Caching; import org.springframework.stereotype.Component; @Component -@CacheConfig(cacheNames = { "addressDemo" }) +@CacheConfig(cacheNames = { "addresses" }) public class CustomerDataService { @Autowired CacheManager cacheManager; + // this method configuration is equivalent to xml configuration + @Cacheable(value = "addresses", key = "#customer.name") + public String getAddress(final Customer customer) { + return customer.getAddress(); + } + /** * The method returns the customer's address, only it doesn't find it the cache- addresses and directory. 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/main/resources/config.xml b/spring-all/src/main/resources/config.xml
index 244e9027ec..23458539b0 100644
--- a/spring-all/src/main/resources/config.xml
+++ b/spring-all/src/main/resources/config.xml
@@ -10,8 +10,7 @@
 
     
 
-    
-    
+    
 
     
     
@@ -21,7 +20,6 @@
             
                 
                 
-                
             
         
     
@@ -34,7 +32,7 @@
     
 
 
-    
+    
     
         
     
diff --git a/spring-all/src/test/java/org/baeldung/caching/test/SpringCachingBehaviorTest.java b/spring-all/src/test/java/org/baeldung/caching/test/SpringCachingBehaviorTest.java
index 0b3edaffb3..a4a3733dd8 100644
--- a/spring-all/src/test/java/org/baeldung/caching/test/SpringCachingBehaviorTest.java
+++ b/spring-all/src/test/java/org/baeldung/caching/test/SpringCachingBehaviorTest.java
@@ -1,11 +1,11 @@
 package org.baeldung.caching.test;
 
+import org.baeldung.caching.config.CachingConfig;
 import org.baeldung.caching.example.Customer;
 import org.baeldung.caching.example.CustomerDataService;
 import org.junit.Test;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
 import org.springframework.stereotype.Component;
+import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
 
 @Component
 public class SpringCachingBehaviorTest {
@@ -13,12 +13,16 @@ public class SpringCachingBehaviorTest {
     @Test
     public void testCaching() {
         @SuppressWarnings("resource")
-        final ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
+        final
+        // final ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
+        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
+        context.register(CachingConfig.class);
+        context.refresh();
         final CustomerDataService service = context.getBean(CustomerDataService.class);
 
         final Customer cust = new Customer("Tom", "67-2, Downing Street, NY");
-        service.getAddress1(cust);
-        service.getAddress1(cust);
+        service.getAddress(cust);
+        service.getAddress(cust);
 
         // fail("Unable to instantiate the CustomerDataService");
     }
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/.classpath b/spring-batch/.classpath
new file mode 100644
index 0000000000..e7ac9faf11
--- /dev/null
+++ b/spring-batch/.classpath
@@ -0,0 +1,31 @@
+
+
+	
+		
+			
+			
+		
+	
+	
+		
+			
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+
diff --git a/spring-batch/.project b/spring-batch/.project
new file mode 100644
index 0000000000..0159a7237c
--- /dev/null
+++ b/spring-batch/.project
@@ -0,0 +1,29 @@
+
+
+	spring-batch
+	
+	
+	
+	
+		
+			org.eclipse.jdt.core.javabuilder
+			
+			
+		
+		
+			org.eclipse.m2e.core.maven2Builder
+			
+			
+		
+		
+			org.springframework.ide.eclipse.core.springbuilder
+			
+			
+		
+	
+	
+		org.springframework.ide.eclipse.core.springnature
+		org.eclipse.jdt.core.javanature
+		org.eclipse.m2e.core.maven2Nature
+	
+
diff --git a/spring-batch/README.md b/spring-batch/README.md
new file mode 100644
index 0000000000..953e652cea
--- /dev/null
+++ b/spring-batch/README.md
@@ -0,0 +1,7 @@
+=========
+
+## Spring Batch
+
+
+### Relevant Articles: 
+- [Introduction to Spring Batch](http://www.baeldung.com/introduction-to-spring-batch)
diff --git a/spring-batch/pom.xml b/spring-batch/pom.xml
new file mode 100644
index 0000000000..c85aeff6f3
--- /dev/null
+++ b/spring-batch/pom.xml
@@ -0,0 +1,43 @@
+
+    4.0.0
+
+    org.baeldung
+    spring-batch
+    0.1-SNAPSHOT
+    jar
+
+    spring-batch
+    http://maven.apache.org
+
+    
+        UTF-8
+        4.2.0.RELEASE
+        3.0.5.RELEASE
+        3.8.11.2
+    
+
+    
+        
+        
+            org.xerial
+            sqlite-jdbc
+            ${sqlite.version}
+        
+        
+            org.springframework
+            spring-oxm
+            ${spring.version}
+        
+        
+            org.springframework
+            spring-jdbc
+            ${spring.version}
+        
+        
+            org.springframework.batch
+            spring-batch-core
+            ${spring.batch.version}
+        
+    
+
+
diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/App.java b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/App.java
new file mode 100644
index 0000000000..2ce4dae6e6
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/App.java
@@ -0,0 +1,32 @@
+package org.baeldung.spring_batch_intro;
+
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+public class App {
+    public static void main(final String[] args) {
+        // Spring Java config
+        final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+        context.register(SpringConfig.class);
+        context.register(SpringBatchConfig.class);
+        context.refresh();
+
+        // Spring xml config
+        // ApplicationContext context = new ClassPathXmlApplicationContext("spring-batch.xml");
+
+        final JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
+        final Job job = (Job) context.getBean("firstBatchJob");
+        System.out.println("Starting the batch job");
+        try {
+            final JobExecution execution = jobLauncher.run(job, new JobParameters());
+            System.out.println("Job Status : " + execution.getStatus());
+            System.out.println("Job succeeded");
+        } catch (final Exception e) {
+            e.printStackTrace();
+            System.out.println("Job failed");
+        }
+    }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000000..9973005c7c
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringBatchConfig.java
@@ -0,0 +1,88 @@
+package org.baeldung.spring_batch_intro;
+
+import java.net.MalformedURLException;
+import java.text.ParseException;
+
+import org.baeldung.spring_batch_intro.model.Transaction;
+import org.baeldung.spring_batch_intro.service.CustomItemProcessor;
+import org.baeldung.spring_batch_intro.service.RecordFieldSetMapper;
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
+import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
+import org.springframework.batch.item.ItemProcessor;
+import org.springframework.batch.item.ItemReader;
+import org.springframework.batch.item.ItemWriter;
+import org.springframework.batch.item.UnexpectedInputException;
+import org.springframework.batch.item.file.FlatFileItemReader;
+import org.springframework.batch.item.file.mapping.DefaultLineMapper;
+import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
+import org.springframework.batch.item.xml.StaxEventItemWriter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.io.Resource;
+import org.springframework.oxm.Marshaller;
+import org.springframework.oxm.jaxb.Jaxb2Marshaller;
+
+public class SpringBatchConfig {
+    @Autowired
+    private JobBuilderFactory jobs;
+
+    @Autowired
+    private StepBuilderFactory steps;
+
+    @Value("input/record.csv")
+    private Resource inputCsv;
+
+    @Value("file:xml/output.xml")
+    private Resource outputXml;
+
+    @Bean
+    public ItemReader itemReader() throws UnexpectedInputException, ParseException {
+        FlatFileItemReader reader = new FlatFileItemReader();
+        DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
+        String[] tokens = { "username", "userid", "transactiondate", "amount" };
+        tokenizer.setNames(tokens);
+        reader.setResource(inputCsv);
+        DefaultLineMapper lineMapper = new DefaultLineMapper();
+        lineMapper.setLineTokenizer(tokenizer);
+        lineMapper.setFieldSetMapper(new RecordFieldSetMapper());
+        reader.setLinesToSkip(1);
+        reader.setLineMapper(lineMapper);
+        return reader;
+    }
+
+    @Bean
+    public ItemProcessor itemProcessor() {
+        return new CustomItemProcessor();
+    }
+
+    @Bean
+    public ItemWriter itemWriter(Marshaller marshaller) throws MalformedURLException {
+        StaxEventItemWriter itemWriter = new StaxEventItemWriter();
+        itemWriter.setMarshaller(marshaller);
+        itemWriter.setRootTagName("transactionRecord");
+        itemWriter.setResource(outputXml);
+        return itemWriter;
+    }
+
+    @Bean
+    public Marshaller marshaller() {
+        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
+        marshaller.setClassesToBeBound(new Class[] { Transaction.class });
+        return marshaller;
+    }
+
+    @Bean
+    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")
+    public Job job(@Qualifier("step1") Step step1) {
+        return jobs.get("firstBatchJob").start(step1).build();
+    }
+
+}
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
new file mode 100644
index 0000000000..ed7d302047
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/SpringConfig.java
@@ -0,0 +1,78 @@
+package org.baeldung.spring_batch_intro;
+
+import java.net.MalformedURLException;
+
+import javax.sql.DataSource;
+
+import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.batch.core.launch.support.SimpleJobLauncher;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
+import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.jdbc.datasource.init.DataSourceInitializer;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+import org.springframework.transaction.PlatformTransactionManager;
+
+@Configuration
+@EnableBatchProcessing
+public class SpringConfig {
+
+    @Value("org/springframework/batch/core/schema-drop-sqlite.sql")
+    private Resource dropReopsitoryTables;
+
+    @Value("org/springframework/batch/core/schema-sqlite.sql")
+    private Resource dataReopsitorySchema;
+
+    @Bean
+    public DataSource dataSource() {
+        DriverManagerDataSource dataSource = new DriverManagerDataSource();
+        dataSource.setDriverClassName("org.sqlite.JDBC");
+        dataSource.setUrl("jdbc:sqlite:repository.sqlite");
+        return dataSource;
+    }
+
+    @Bean
+    public DataSourceInitializer dataSourceInitializer(DataSource dataSource) throws MalformedURLException {
+        ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
+
+        databasePopulator.addScript(dropReopsitoryTables);
+        databasePopulator.addScript(dataReopsitorySchema);
+        databasePopulator.setIgnoreFailedDrops(true);
+
+        DataSourceInitializer initializer = new DataSourceInitializer();
+        initializer.setDataSource(dataSource);
+        initializer.setDatabasePopulator(databasePopulator);
+
+        return initializer;
+    }
+
+    private JobRepository getJobRepository() throws Exception {
+        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
+        factory.setDataSource(dataSource());
+        factory.setTransactionManager(getTransactionManager());
+        // JobRepositoryFactoryBean's methods Throws Generic Exception,
+        // it would have been better to have a specific one
+        factory.afterPropertiesSet();
+        return (JobRepository) factory.getObject();
+    }
+
+    private PlatformTransactionManager getTransactionManager() {
+        return new ResourcelessTransactionManager();
+    }
+
+    public JobLauncher getJobLauncher() throws Exception {
+        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
+        // SimpleJobLauncher's methods Throws Generic Exception,
+        // it would have been better to have a specific one
+        jobLauncher.setJobRepository(getJobRepository());
+        jobLauncher.afterPropertiesSet();
+        return jobLauncher;
+    }
+
+}
\ No newline at end of file
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
new file mode 100644
index 0000000000..3b2b9610f2
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/model/Transaction.java
@@ -0,0 +1,54 @@
+package org.baeldung.spring_batch_intro.model;
+
+import java.util.Date;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@SuppressWarnings("restriction")
+@XmlRootElement(name = "transactionRecord")
+public class Transaction {
+    private String username;
+    private int userId;
+    private Date transactionDate;
+    private double amount;
+
+    /* getters and setters for the attributes */
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public int getUserId() {
+        return userId;
+    }
+
+    public void setUserId(int userId) {
+        this.userId = userId;
+    }
+
+    public Date getTransactionDate() {
+        return transactionDate;
+    }
+
+    public void setTransactionDate(Date transactionDate) {
+        this.transactionDate = transactionDate;
+    }
+
+    public double getAmount() {
+        return amount;
+    }
+
+    public void setAmount(double amount) {
+        this.amount = amount;
+    }
+
+    @Override
+    public String toString() {
+        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
new file mode 100644
index 0000000000..ebee1d2802
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/CustomItemProcessor.java
@@ -0,0 +1,12 @@
+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 Transaction process(Transaction item) {
+        System.out.println("Processing..." + item);
+        return item;
+    }
+}
\ No newline at end of file
diff --git a/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/RecordFieldSetMapper.java b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/RecordFieldSetMapper.java
new file mode 100644
index 0000000000..94f9e7d94e
--- /dev/null
+++ b/spring-batch/src/main/java/org/baeldung/spring_batch_intro/service/RecordFieldSetMapper.java
@@ -0,0 +1,35 @@
+package org.baeldung.spring_batch_intro.service;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+import org.baeldung.spring_batch_intro.model.Transaction;
+import org.springframework.batch.item.file.mapping.FieldSetMapper;
+import org.springframework.batch.item.file.transform.FieldSet;
+import org.springframework.validation.BindException;
+
+public class RecordFieldSetMapper implements FieldSetMapper {
+
+    public Transaction mapFieldSet(FieldSet fieldSet) throws BindException {
+
+        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
+        Transaction transaction = new Transaction();
+        // you can either use the indices or custom names
+        // I personally prefer the custom names easy for debugging and
+        // validating the pipelines
+        transaction.setUsername(fieldSet.readString("username"));
+        transaction.setUserId(fieldSet.readInt("userid"));
+        transaction.setAmount(fieldSet.readDouble(3));
+        // Converting the date
+        String dateString = fieldSet.readString(2);
+        try {
+            transaction.setTransactionDate(dateFormat.parse(dateString));
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+
+        return transaction;
+
+    }
+
+}
diff --git a/spring-batch/src/main/resources/input/record.csv b/spring-batch/src/main/resources/input/record.csv
new file mode 100644
index 0000000000..e554becb2a
--- /dev/null
+++ b/spring-batch/src/main/resources/input/record.csv
@@ -0,0 +1,4 @@
+username, user_id, transaction_date, transaction_amount
+devendra, 1234, 31/10/2015, 10000
+john, 2134, 3/12/2015, 12321
+robin, 2134, 2/02/2015, 23411
\ No newline at end of file
diff --git a/spring-batch/src/main/resources/spring-batch-intro.xml b/spring-batch/src/main/resources/spring-batch-intro.xml
new file mode 100644
index 0000000000..93606d232f
--- /dev/null
+++ b/spring-batch/src/main/resources/spring-batch-intro.xml
@@ -0,0 +1,57 @@
+
+
+    
+
+    
+        
+        
+            
+                
+                    
+                        
+                    
+                
+                
+                    
+                
+            
+        
+        
+    
+
+    
+
+    
+        
+        
+        
+    
+
+    
+        
+            
+                org.baeldung.spring_batch_intro.model.Transaction
+            
+        
+    
+
+    
+        
+            
+                
+                
+            
+        
+    
+
diff --git a/spring-batch/src/main/resources/spring.xml b/spring-batch/src/main/resources/spring.xml
new file mode 100644
index 0000000000..dea261c5e6
--- /dev/null
+++ b/spring-batch/src/main/resources/spring.xml
@@ -0,0 +1,45 @@
+
+
+    
+    
+        
+        
+        
+        
+    
+
+    
+    
+        
+        
+    
+
+    
+    
+
+    
+    
+        
+        
+        
+    
+
+    
+
+    
+        
+    
+
+
\ No newline at end of file
diff --git a/spring-batch/xml/output.xml b/spring-batch/xml/output.xml
new file mode 100644
index 0000000000..acf4969341
--- /dev/null
+++ b/spring-batch/xml/output.xml
@@ -0,0 +1 @@
+10000.02015-10-31T00:00:00+05:301234devendra12321.02015-12-03T00:00:00+05:302134john23411.02015-02-02T00:00:00+05:302134robin
\ No newline at end of file
diff --git a/spring-data-cassandra/.classpath b/spring-data-cassandra/.classpath
new file mode 100644
index 0000000000..698778fef3
--- /dev/null
+++ b/spring-data-cassandra/.classpath
@@ -0,0 +1,31 @@
+
+
+	
+		
+			
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+
diff --git a/spring-data-cassandra/.project b/spring-data-cassandra/.project
new file mode 100644
index 0000000000..239fa4f002
--- /dev/null
+++ b/spring-data-cassandra/.project
@@ -0,0 +1,29 @@
+
+
+	spring-data-cassandra
+	
+	
+	
+	
+		
+			org.eclipse.jdt.core.javabuilder
+			
+			
+		
+		
+			org.eclipse.m2e.core.maven2Builder
+			
+			
+		
+		
+			org.springframework.ide.eclipse.core.springbuilder
+			
+			
+		
+	
+	
+		org.springframework.ide.eclipse.core.springnature
+		org.eclipse.jdt.core.javanature
+		org.eclipse.m2e.core.maven2Nature
+	
+
diff --git a/spring-data-cassandra/README.md b/spring-data-cassandra/README.md
index a245ff62a1..456eefcf18 100644
--- a/spring-data-cassandra/README.md
+++ b/spring-data-cassandra/README.md
@@ -2,6 +2,7 @@
 
 ### Relevant Articles:
 - [Introduction to Spring Data Cassandra](http://www.baeldung.com/spring-data-cassandra-tutorial)
+- [Using the CassandraTemplate from Spring Data](http://www.baeldung.com/spring-data-cassandratemplate-cqltemplate)
 
 ### Build the Project with Tests Running
 ```
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-cassandra/src/main/java/org/baeldung/spring/data/cassandra/config/CassandraConfig.java b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/config/CassandraConfig.java
index 5f2c4c6d47..2edd5551a5 100644
--- a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/config/CassandraConfig.java
+++ b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/config/CassandraConfig.java
@@ -17,8 +17,8 @@ import org.springframework.data.cassandra.repository.config.EnableCassandraRepos
 @PropertySource(value = { "classpath:cassandra.properties" })
 @EnableCassandraRepositories(basePackages = "org.baeldung.spring.data.cassandra.repository")
 public class CassandraConfig extends AbstractCassandraConfiguration {
-
     private static final Log LOGGER = LogFactory.getLog(CassandraConfig.class);
+
     @Autowired
     private Environment environment;
 
@@ -27,15 +27,17 @@ public class CassandraConfig extends AbstractCassandraConfiguration {
         return environment.getProperty("cassandra.keyspace");
     }
 
+    @Override
     @Bean
     public CassandraClusterFactoryBean cluster() {
-        CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
+        final CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
         cluster.setContactPoints(environment.getProperty("cassandra.contactpoints"));
         cluster.setPort(Integer.parseInt(environment.getProperty("cassandra.port")));
         LOGGER.info("Cluster created with contact points [" + environment.getProperty("cassandra.contactpoints") + "] " + "& port [" + Integer.parseInt(environment.getProperty("cassandra.port")) + "].");
         return cluster;
     }
 
+    @Override
     @Bean
     public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
         return new BasicCassandraMappingContext();
diff --git a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/model/Book.java b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/model/Book.java
index 6c099d99bc..a8ec81d6b5 100644
--- a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/model/Book.java
+++ b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/model/Book.java
@@ -1,28 +1,31 @@
 package org.baeldung.spring.data.cassandra.model;
 
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
 import org.springframework.cassandra.core.Ordering;
 import org.springframework.cassandra.core.PrimaryKeyType;
 import org.springframework.data.cassandra.mapping.Column;
 import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
 import org.springframework.data.cassandra.mapping.Table;
 
-import java.util.HashSet;
-import java.util.Set;
-import java.util.UUID;
-
 @Table
 public class Book {
+
     @PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.DESCENDING)
     private UUID id;
+
     @PrimaryKeyColumn(name = "title", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
     private String title;
 
     @PrimaryKeyColumn(name = "publisher", ordinal = 2, type = PrimaryKeyType.PARTITIONED)
     private String publisher;
+
     @Column
     private Set tags = new HashSet<>();
 
-    public Book(UUID id, String title, String publisher, Set tags) {
+    public Book(final UUID id, final String title, final String publisher, final Set tags) {
         this.id = id;
         this.title = title;
         this.publisher = publisher;
@@ -45,19 +48,20 @@ public class Book {
         return tags;
     }
 
-    public void setId(UUID id) {
+    public void setId(final UUID id) {
         this.id = id;
     }
 
-    public void setTitle(String title) {
+    public void setTitle(final String title) {
         this.title = title;
     }
 
-    public void setPublisher(String publisher) {
+    public void setPublisher(final String publisher) {
         this.publisher = publisher;
     }
 
-    public void setTags(Set tags) {
+    public void setTags(final Set tags) {
         this.tags = tags;
     }
+
 }
diff --git a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/BookRepository.java b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/BookRepository.java
index e37ae78b59..66d656ac3a 100644
--- a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/BookRepository.java
+++ b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/BookRepository.java
@@ -7,6 +7,8 @@ import org.springframework.stereotype.Repository;
 
 @Repository
 public interface BookRepository extends CassandraRepository {
+
     @Query("select * from book where title = ?0 and publisher=?1")
     Iterable findByTitleAndPublisher(String title, String publisher);
+
 }
diff --git a/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/BookRepositoryIntegrationTest.java b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/BookRepositoryIntegrationTest.java
index e5a7237145..8cbcdc3195 100644
--- a/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/BookRepositoryIntegrationTest.java
+++ b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/BookRepositoryIntegrationTest.java
@@ -1,9 +1,11 @@
 package org.baeldung.spring.data.cassandra.repository;
 
-import com.datastax.driver.core.Cluster;
-import com.datastax.driver.core.Session;
-import com.datastax.driver.core.utils.UUIDs;
-import com.google.common.collect.ImmutableSet;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import java.io.IOException;
+import java.util.HashMap;
+
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -11,7 +13,11 @@ import org.apache.thrift.transport.TTransportException;
 import org.baeldung.spring.data.cassandra.config.CassandraConfig;
 import org.baeldung.spring.data.cassandra.model.Book;
 import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
-import org.junit.*;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cassandra.core.cql.CqlIdentifier;
@@ -19,16 +25,14 @@ import org.springframework.data.cassandra.core.CassandraAdminOperations;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
-import java.io.IOException;
-import java.util.HashMap;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.utils.UUIDs;
+import com.google.common.collect.ImmutableSet;
 
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration(classes = CassandraConfig.class)
 public class BookRepositoryIntegrationTest {
-
     private static final Log LOGGER = LogFactory.getLog(BookRepositoryIntegrationTest.class);
 
     public static final String KEYSPACE_CREATION_QUERY = "CREATE KEYSPACE IF NOT EXISTS testKeySpace WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };";
@@ -43,13 +47,14 @@ public class BookRepositoryIntegrationTest {
     @Autowired
     private CassandraAdminOperations adminTemplate;
 
+    //
+
     @BeforeClass
     public static void startCassandraEmbedded() throws InterruptedException, TTransportException, ConfigurationException, IOException {
         EmbeddedCassandraServerHelper.startEmbeddedCassandra();
-        Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1")
-                .withPort(9142).build();
+        final Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withPort(9142).build();
         LOGGER.info("Server Started at 127.0.0.1:9142... ");
-        Session session = cluster.connect();
+        final Session session = cluster.connect();
         session.execute(KEYSPACE_CREATION_QUERY);
         session.execute(KEYSPACE_ACTIVATE_QUERY);
         LOGGER.info("KeySpace created and activated.");
@@ -63,54 +68,54 @@ public class BookRepositoryIntegrationTest {
 
     @Test
     public void whenSavingBook_thenAvailableOnRetrieval() {
-        Book javaBook = new Book(UUIDs.timeBased(), "Head First Java",
-                "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
         bookRepository.save(ImmutableSet.of(javaBook));
-        Iterable books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
+        final Iterable books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
         assertEquals(javaBook.getId(), books.iterator().next().getId());
     }
 
     @Test
     public void whenUpdatingBooks_thenAvailableOnRetrieval() {
-        Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
         bookRepository.save(ImmutableSet.of(javaBook));
-        Iterable books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
+        final Iterable books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
         javaBook.setTitle("Head First Java Second Edition");
         bookRepository.save(ImmutableSet.of(javaBook));
-        Iterable updateBooks = bookRepository.findByTitleAndPublisher("Head First Java Second Edition", "O'Reilly Media");
+        final Iterable updateBooks = bookRepository.findByTitleAndPublisher("Head First Java Second Edition", "O'Reilly Media");
         assertEquals(javaBook.getTitle(), updateBooks.iterator().next().getTitle());
     }
 
     @Test(expected = java.util.NoSuchElementException.class)
     public void whenDeletingExistingBooks_thenNotAvailableOnRetrieval() {
-        Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
         bookRepository.save(ImmutableSet.of(javaBook));
         bookRepository.delete(javaBook);
-        Iterable books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
+        final Iterable books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
         assertNotEquals(javaBook.getId(), books.iterator().next().getId());
     }
 
     @Test
     public void whenSavingBooks_thenAllShouldAvailableOnRetrieval() {
-        Book javaBook = new Book(UUIDs.timeBased(), "Head First Java",
-                "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
-        Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns",
-                "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
         bookRepository.save(ImmutableSet.of(javaBook));
         bookRepository.save(ImmutableSet.of(dPatternBook));
-        Iterable books = bookRepository.findAll();
+        final Iterable books = bookRepository.findAll();
         int bookCount = 0;
-        for (Book book : books) bookCount++;
+        for (final Book book : books) {
+            bookCount++;
+        }
         assertEquals(bookCount, 2);
     }
 
     @After
     public void dropTable() {
-       adminTemplate.dropTable(CqlIdentifier.cqlId(DATA_TABLE_NAME));
+        adminTemplate.dropTable(CqlIdentifier.cqlId(DATA_TABLE_NAME));
     }
 
     @AfterClass
     public static void stopCassandraEmbedded() {
         EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
     }
+
 }
diff --git a/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/CassandraTemplateIntegrationTest.java b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/CassandraTemplateIntegrationTest.java
index 35de508641..e331ac3cd4 100644
--- a/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/CassandraTemplateIntegrationTest.java
+++ b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/CassandraTemplateIntegrationTest.java
@@ -1,11 +1,15 @@
 package org.baeldung.spring.data.cassandra.repository;
 
-import com.datastax.driver.core.Cluster;
-import com.datastax.driver.core.Session;
-import com.datastax.driver.core.querybuilder.QueryBuilder;
-import com.datastax.driver.core.querybuilder.Select;
-import com.datastax.driver.core.utils.UUIDs;
-import com.google.common.collect.ImmutableSet;
+import static junit.framework.TestCase.assertNull;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -13,7 +17,11 @@ import org.apache.thrift.transport.TTransportException;
 import org.baeldung.spring.data.cassandra.config.CassandraConfig;
 import org.baeldung.spring.data.cassandra.model.Book;
 import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
-import org.junit.*;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cassandra.core.cql.CqlIdentifier;
@@ -22,20 +30,16 @@ import org.springframework.data.cassandra.core.CassandraOperations;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import static junit.framework.TestCase.assertNull;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+import com.datastax.driver.core.querybuilder.Select;
+import com.datastax.driver.core.utils.UUIDs;
+import com.google.common.collect.ImmutableSet;
 
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration(classes = CassandraConfig.class)
 public class CassandraTemplateIntegrationTest {
-
     private static final Log LOGGER = LogFactory.getLog(CassandraTemplateIntegrationTest.class);
 
     public static final String KEYSPACE_CREATION_QUERY = "CREATE KEYSPACE IF NOT EXISTS testKeySpace " + "WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };";
@@ -50,12 +54,14 @@ public class CassandraTemplateIntegrationTest {
     @Autowired
     private CassandraOperations cassandraTemplate;
 
+    //
+
     @BeforeClass
     public static void startCassandraEmbedded() throws InterruptedException, TTransportException, ConfigurationException, IOException {
         EmbeddedCassandraServerHelper.startEmbeddedCassandra();
-        Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withPort(9142).build();
+        final Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withPort(9142).build();
         LOGGER.info("Server Started at 127.0.0.1:9142... ");
-        Session session = cluster.connect();
+        final Session session = cluster.connect();
         session.execute(KEYSPACE_CREATION_QUERY);
         session.execute(KEYSPACE_ACTIVATE_QUERY);
         LOGGER.info("KeySpace created and activated.");
@@ -69,24 +75,24 @@ public class CassandraTemplateIntegrationTest {
 
     @Test
     public void whenSavingBook_thenAvailableOnRetrieval() {
-        Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
         cassandraTemplate.insert(javaBook);
-        Select select = QueryBuilder.select().from("book").where(QueryBuilder.eq("title", "Head First Java")).and(QueryBuilder.eq("publisher", "O'Reilly Media")).limit(10);
-        Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
+        final Select select = QueryBuilder.select().from("book").where(QueryBuilder.eq("title", "Head First Java")).and(QueryBuilder.eq("publisher", "O'Reilly Media")).limit(10);
+        final Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
         assertEquals(javaBook.getId(), retrievedBook.getId());
     }
 
     @Test
     public void whenSavingBooks_thenAllAvailableOnRetrieval() {
-        Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
-        Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
-        List bookList = new ArrayList<>();
+        final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final List bookList = new ArrayList<>();
         bookList.add(javaBook);
         bookList.add(dPatternBook);
         cassandraTemplate.insert(bookList);
 
-        Select select = QueryBuilder.select().from("book").limit(10);
-        List retrievedBooks = cassandraTemplate.select(select, Book.class);
+        final Select select = QueryBuilder.select().from("book").limit(10);
+        final List retrievedBooks = cassandraTemplate.select(select, Book.class);
         assertThat(retrievedBooks.size(), is(2));
         assertEquals(javaBook.getId(), retrievedBooks.get(0).getId());
         assertEquals(dPatternBook.getId(), retrievedBooks.get(1).getId());
@@ -94,45 +100,45 @@ public class CassandraTemplateIntegrationTest {
 
     @Test
     public void whenUpdatingBook_thenShouldUpdatedOnRetrieval() {
-        Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
         cassandraTemplate.insert(javaBook);
-        Select select = QueryBuilder.select().from("book").limit(10);
-        Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
+        final Select select = QueryBuilder.select().from("book").limit(10);
+        final Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
         retrievedBook.setTags(ImmutableSet.of("Java", "Programming"));
         cassandraTemplate.update(retrievedBook);
-        Book retrievedUpdatedBook = cassandraTemplate.selectOne(select, Book.class);
+        final Book retrievedUpdatedBook = cassandraTemplate.selectOne(select, Book.class);
         assertEquals(retrievedBook.getTags(), retrievedUpdatedBook.getTags());
     }
 
     @Test
     public void whenDeletingASelectedBook_thenNotAvailableOnRetrieval() throws InterruptedException {
-        Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "OReilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "OReilly Media", ImmutableSet.of("Computer", "Software"));
         cassandraTemplate.insert(javaBook);
         cassandraTemplate.delete(javaBook);
-        Select select = QueryBuilder.select().from("book").limit(10);
-        Book retrievedUpdatedBook = cassandraTemplate.selectOne(select, Book.class);
+        final Select select = QueryBuilder.select().from("book").limit(10);
+        final Book retrievedUpdatedBook = cassandraTemplate.selectOne(select, Book.class);
         assertNull(retrievedUpdatedBook);
     }
 
     @Test
     public void whenDeletingAllBooks_thenNotAvailableOnRetrieval() {
-        Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
-        Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
         cassandraTemplate.insert(javaBook);
         cassandraTemplate.insert(dPatternBook);
         cassandraTemplate.deleteAll(Book.class);
-        Select select = QueryBuilder.select().from("book").limit(10);
-        Book retrievedUpdatedBook = cassandraTemplate.selectOne(select, Book.class);
+        final Select select = QueryBuilder.select().from("book").limit(10);
+        final Book retrievedUpdatedBook = cassandraTemplate.selectOne(select, Book.class);
         assertNull(retrievedUpdatedBook);
     }
 
     @Test
     public void whenAddingBooks_thenCountShouldBeCorrectOnRetrieval() {
-        Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
-        Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
+        final Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
         cassandraTemplate.insert(javaBook);
         cassandraTemplate.insert(dPatternBook);
-        long bookCount = cassandraTemplate.count(Book.class);
+        final long bookCount = cassandraTemplate.count(Book.class);
         assertEquals(2, bookCount);
     }
 
diff --git a/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/CQLQueriesIntegrationTest.java b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/CqlQueriesIntegrationTest.java
similarity index 69%
rename from spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/CQLQueriesIntegrationTest.java
rename to spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/CqlQueriesIntegrationTest.java
index 031b5c0b6f..f7e42ae23b 100644
--- a/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/CQLQueriesIntegrationTest.java
+++ b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/CqlQueriesIntegrationTest.java
@@ -1,12 +1,13 @@
 package org.baeldung.spring.data.cassandra.repository;
 
-import com.datastax.driver.core.Cluster;
-import com.datastax.driver.core.Session;
-import com.datastax.driver.core.querybuilder.Insert;
-import com.datastax.driver.core.querybuilder.QueryBuilder;
-import com.datastax.driver.core.querybuilder.Select;
-import com.datastax.driver.core.utils.UUIDs;
-import com.google.common.collect.ImmutableSet;
+import static junit.framework.TestCase.assertEquals;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.UUID;
+
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -14,7 +15,11 @@ import org.apache.thrift.transport.TTransportException;
 import org.baeldung.spring.data.cassandra.config.CassandraConfig;
 import org.baeldung.spring.data.cassandra.model.Book;
 import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
-import org.junit.*;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cassandra.core.cql.CqlIdentifier;
@@ -23,19 +28,18 @@ import org.springframework.data.cassandra.core.CassandraOperations;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.UUID;
-
-import static junit.framework.TestCase.assertEquals;
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.Session;
+import com.datastax.driver.core.querybuilder.Insert;
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+import com.datastax.driver.core.querybuilder.Select;
+import com.datastax.driver.core.utils.UUIDs;
+import com.google.common.collect.ImmutableSet;
 
 @RunWith(SpringJUnit4ClassRunner.class)
 @ContextConfiguration(classes = CassandraConfig.class)
-public class CQLQueriesIntegrationTest {
-
-    private static final Log LOGGER = LogFactory.getLog(CQLQueriesIntegrationTest.class);
+public class CqlQueriesIntegrationTest {
+    private static final Log LOGGER = LogFactory.getLog(CqlQueriesIntegrationTest.class);
 
     public static final String KEYSPACE_CREATION_QUERY = "CREATE KEYSPACE IF NOT EXISTS testKeySpace " + "WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };";
 
@@ -49,12 +53,14 @@ public class CQLQueriesIntegrationTest {
     @Autowired
     private CassandraOperations cassandraTemplate;
 
+    //
+
     @BeforeClass
     public static void startCassandraEmbedded() throws InterruptedException, TTransportException, ConfigurationException, IOException {
         EmbeddedCassandraServerHelper.startEmbeddedCassandra(25000);
-        Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withPort(9142).build();
+        final Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withPort(9142).build();
         LOGGER.info("Server Started at 127.0.0.1:9142... ");
-        Session session = cluster.connect();
+        final Session session = cluster.connect();
         session.execute(KEYSPACE_CREATION_QUERY);
         session.execute(KEYSPACE_ACTIVATE_QUERY);
         LOGGER.info("KeySpace created and activated.");
@@ -68,40 +74,40 @@ public class CQLQueriesIntegrationTest {
 
     @Test
     public void whenSavingBook_thenAvailableOnRetrieval_usingQueryBuilder() {
-        UUID uuid = UUIDs.timeBased();
-        Insert insert = QueryBuilder.insertInto(DATA_TABLE_NAME).value("id", uuid).value("title", "Head First Java").value("publisher", "OReilly Media").value("tags", ImmutableSet.of("Software"));
+        final UUID uuid = UUIDs.timeBased();
+        final Insert insert = QueryBuilder.insertInto(DATA_TABLE_NAME).value("id", uuid).value("title", "Head First Java").value("publisher", "OReilly Media").value("tags", ImmutableSet.of("Software"));
         cassandraTemplate.execute(insert);
-        Select select = QueryBuilder.select().from("book").limit(10);
-        Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
+        final Select select = QueryBuilder.select().from("book").limit(10);
+        final Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
         assertEquals(uuid, retrievedBook.getId());
     }
 
     @Test
     public void whenSavingBook_thenAvailableOnRetrieval_usingCQLStatements() {
-        UUID uuid = UUIDs.timeBased();
-        String insertCql = "insert into book (id, title, publisher, tags) values " + "(" + uuid + ", 'Head First Java', 'OReilly Media', {'Software'})";
+        final UUID uuid = UUIDs.timeBased();
+        final String insertCql = "insert into book (id, title, publisher, tags) values " + "(" + uuid + ", 'Head First Java', 'OReilly Media', {'Software'})";
         cassandraTemplate.execute(insertCql);
-        Select select = QueryBuilder.select().from("book").limit(10);
-        Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
+        final Select select = QueryBuilder.select().from("book").limit(10);
+        final Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
         assertEquals(uuid, retrievedBook.getId());
     }
 
     @Test
     public void whenSavingBook_thenAvailableOnRetrieval_usingPreparedStatements() throws InterruptedException {
-        UUID uuid = UUIDs.timeBased();
-        String insertPreparedCql = "insert into book (id, title, publisher, tags) values (?, ?, ?, ?)";
-        List singleBookArgsList = new ArrayList<>();
-        List> bookList = new ArrayList<>();
+        final UUID uuid = UUIDs.timeBased();
+        final String insertPreparedCql = "insert into book (id, title, publisher, tags) values (?, ?, ?, ?)";
+        final List singleBookArgsList = new ArrayList<>();
+        final List> bookList = new ArrayList<>();
         singleBookArgsList.add(uuid);
         singleBookArgsList.add("Head First Java");
         singleBookArgsList.add("OReilly Media");
         singleBookArgsList.add(ImmutableSet.of("Software"));
         bookList.add(singleBookArgsList);
         cassandraTemplate.ingest(insertPreparedCql, bookList);
-        //This may not be required, just added to avoid any transient issues
+        // This may not be required, just added to avoid any transient issues
         Thread.sleep(5000);
-        Select select = QueryBuilder.select().from("book");
-        Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
+        final Select select = QueryBuilder.select().from("book");
+        final Book retrievedBook = cassandraTemplate.selectOne(select, Book.class);
         assertEquals(uuid, retrievedBook.getId());
     }
 
@@ -114,4 +120,5 @@ public class CQLQueriesIntegrationTest {
     public static void stopCassandraEmbedded() {
         EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
     }
+
 }
diff --git a/spring-data-elasticsearch/.classpath b/spring-data-elasticsearch/.classpath
new file mode 100644
index 0000000000..698778fef3
--- /dev/null
+++ b/spring-data-elasticsearch/.classpath
@@ -0,0 +1,31 @@
+
+
+	
+		
+			
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+
diff --git a/spring-data-elasticsearch/.project b/spring-data-elasticsearch/.project
new file mode 100644
index 0000000000..09b9a781ed
--- /dev/null
+++ b/spring-data-elasticsearch/.project
@@ -0,0 +1,29 @@
+
+
+	spring-data-elasticsearch
+	
+	
+	
+	
+		
+			org.eclipse.jdt.core.javabuilder
+			
+			
+		
+		
+			org.eclipse.m2e.core.maven2Builder
+			
+			
+		
+		
+			org.springframework.ide.eclipse.core.springbuilder
+			
+			
+		
+	
+	
+		org.springframework.ide.eclipse.core.springnature
+		org.eclipse.jdt.core.javanature
+		org.eclipse.m2e.core.maven2Nature
+	
+
diff --git a/spring-data-elasticsearch/README.md b/spring-data-elasticsearch/README.md
new file mode 100644
index 0000000000..0dae92e0e7
--- /dev/null
+++ b/spring-data-elasticsearch/README.md
@@ -0,0 +1,12 @@
+## Spring Data Elasticsearch
+
+### Build the Project with Tests Running
+```
+mvn clean install
+```
+
+### Run Tests Directly
+```
+mvn test
+```
+
diff --git a/spring-data-elasticsearch/pom.xml b/spring-data-elasticsearch/pom.xml
new file mode 100644
index 0000000000..7ac6dd0fcf
--- /dev/null
+++ b/spring-data-elasticsearch/pom.xml
@@ -0,0 +1,78 @@
+
+	4.0.0
+
+	org.baeldung
+	spring-data-elasticsearch
+	0.0.1-SNAPSHOT
+	jar
+
+	spring-data-elasticsearch
+
+	
+		UTF-8
+		1.3.2.RELEASE
+		4.2.2.RELEASE
+		4.11
+		1.7.12
+		1.1.3
+		1.3.2.RELEASE
+	
+
+	
+		
+			org.springframework
+			spring-core
+			${org.springframework.version}
+		
+		
+			junit
+			junit-dep
+			${junit.version}
+			test
+		
+		
+			org.springframework
+			spring-test
+			${org.springframework.version}
+			test
+		
+		
+			org.springframework.data
+			spring-data-elasticsearch
+			${elasticsearch.version}
+		
+		
+			org.slf4j
+			slf4j-api
+			${org.slf4j.version}
+		
+		
+			ch.qos.logback
+			logback-classic
+			${logback.version}
+		
+		
+			org.slf4j
+			jcl-over-slf4j
+			${org.slf4j.version}
+		
+		
+			org.slf4j
+			log4j-over-slf4j
+			${org.slf4j.version}
+		
+	
+	
+		
+			
+				maven-compiler-plugin
+				2.3.2
+				
+					1.8
+					1.8
+				
+			
+		
+	
+
diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java
new file mode 100644
index 0000000000..78e4083a28
--- /dev/null
+++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java
@@ -0,0 +1,53 @@
+package com.baeldung.spring.data.es.config;
+
+import org.elasticsearch.common.settings.ImmutableSettings;
+import org.elasticsearch.node.NodeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
+import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
+import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+@Configuration
+@EnableElasticsearchRepositories(basePackages = "com.baeldung.repository")
+@ComponentScan(basePackages = {"com.baeldung.spring.data.es.service"})
+public class Config {
+
+    private static Logger logger = LoggerFactory.getLogger(Config.class);
+
+    @Bean
+    public NodeBuilder nodeBuilder() {
+        return new NodeBuilder();
+    }
+
+    @Bean
+    public ElasticsearchOperations elasticsearchTemplate() {
+
+        try {
+            Path tmpDir = Files.createTempDirectory(Paths.get(System.getProperty("java.io.tmpdir")), "elasticsearch_data");
+
+            ImmutableSettings.Builder elasticsearchSettings = ImmutableSettings.settingsBuilder()
+                    .put("http.enabled", "false")
+                    .put("path.data", tmpDir.toAbsolutePath().toString());
+
+            logger.debug(tmpDir.toAbsolutePath().toString());
+
+            return new ElasticsearchTemplate(nodeBuilder()
+                    .local(true)
+                    .settings(elasticsearchSettings.build())
+                    .node()
+                    .client());
+        } catch (IOException ioex) {
+            logger.error("Cannot create temp dir", ioex);
+            throw new RuntimeException();
+        }
+    }
+}
diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/dao/ArticleRepository.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/dao/ArticleRepository.java
new file mode 100644
index 0000000000..313eba5b36
--- /dev/null
+++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/dao/ArticleRepository.java
@@ -0,0 +1,15 @@
+package com.baeldung.spring.data.es.dao;
+
+import com.baeldung.spring.data.es.model.Article;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.elasticsearch.annotations.Query;
+import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
+
+public interface ArticleRepository extends ElasticsearchRepository {
+
+    Page
findByAuthorsName(String name, Pageable pageable); + + @Query("{\"bool\": {\"must\": [{\"match\": {\"authors.name\": \"?0\"}}]}}") + Page
findByAuthorsNameUsingCustomQuery(String name, Pageable pageable); +} diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Article.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Article.java new file mode 100644 index 0000000000..dd472982ce --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Article.java @@ -0,0 +1,60 @@ +package com.baeldung.spring.data.es.model; + +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldIndex; +import org.springframework.data.elasticsearch.annotations.FieldType; + +import java.util.List; + +@Document(indexName = "blog", type = "article") +public class Article { + + @Id + private String id; + @Field(type = FieldType.String, index = FieldIndex.not_analyzed) + private String title; + @Field(type = FieldType.Nested) + private List authors; + + public Article() { + } + + public Article(String title) { + this.title = title; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getAuthors() { + return authors; + } + + public void setAuthors(List authors) { + this.authors = authors; + } + + @Override + public String toString() { + return "Article{" + + "id='" + id + '\'' + + ", title='" + title + '\'' + + ", authors=" + authors + + '}'; + } +} diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Author.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Author.java new file mode 100644 index 0000000000..c335c4534a --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Author.java @@ -0,0 +1,28 @@ +package com.baeldung.spring.data.es.model; + +public class Author { + + private String name; + + public Author() { + } + + public Author(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "Author{" + + "name='" + name + '\'' + + '}'; + } +} diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/repository/ArticleRepository.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/repository/ArticleRepository.java new file mode 100644 index 0000000000..27628950d7 --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/repository/ArticleRepository.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.data.es.repository; + +import com.baeldung.spring.data.es.model.Article; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.annotations.Query; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +public interface ArticleRepository extends ElasticsearchRepository { + + Page
findByAuthorsName(String name, Pageable pageable); + + @Query("{\"bool\": {\"must\": [{\"match\": {\"authors.name\": \"?0\"}}]}}") + Page
findByAuthorsNameUsingCustomQuery(String name, Pageable pageable); +} diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleService.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleService.java new file mode 100644 index 0000000000..760bad4b01 --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleService.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.data.es.service; + +import com.baeldung.spring.data.es.model.Article; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +public interface ArticleService { + Article save(Article article); + Article findOne(String id); + Iterable
findAll(); + Page
findByAuthorName(String name, Pageable pageable); + Page
findByAuthorNameUsingCustomQuery(String name, Pageable pageable); + long count(); + void delete(Article article); +} diff --git a/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleServiceImpl.java b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleServiceImpl.java new file mode 100644 index 0000000000..3bb6e6a0e0 --- /dev/null +++ b/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleServiceImpl.java @@ -0,0 +1,54 @@ +package com.baeldung.spring.data.es.service; + +import com.baeldung.spring.data.es.repository.ArticleRepository; +import com.baeldung.spring.data.es.model.Article; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +@Service +public class ArticleServiceImpl implements ArticleService { + + private ArticleRepository articleRepository; + + @Autowired + public void setArticleRepository(ArticleRepository articleRepository) { + this.articleRepository = articleRepository; + } + + @Override + public Article save(Article article) { + return articleRepository.save(article); + } + + @Override + public Article findOne(String id) { + return articleRepository.findOne(id); + } + + @Override + public Iterable
findAll() { + return articleRepository.findAll(); + } + + @Override + public Page
findByAuthorName(String name, Pageable pageable) { + return articleRepository.findByAuthorsName(name, pageable); + } + + @Override + public Page
findByAuthorNameUsingCustomQuery(String name, Pageable pageable) { + return articleRepository.findByAuthorsNameUsingCustomQuery(name, pageable); + } + + @Override + public long count() { + return articleRepository.count(); + } + + @Override + public void delete(Article article) { + articleRepository.delete(article); + } +} diff --git a/spring-data-elasticsearch/src/main/resources/logback.xml b/spring-data-elasticsearch/src/main/resources/logback.xml new file mode 100644 index 0000000000..37a9e2edbf --- /dev/null +++ b/spring-data-elasticsearch/src/main/resources/logback.xml @@ -0,0 +1,20 @@ + + + + + elasticsearch - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchTest.java b/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchTest.java new file mode 100644 index 0000000000..34ccfd788e --- /dev/null +++ b/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchTest.java @@ -0,0 +1,129 @@ +package com.baeldung.spring.data.es; + +import com.baeldung.spring.data.es.config.Config; +import com.baeldung.spring.data.es.model.Article; +import com.baeldung.spring.data.es.model.Author; +import com.baeldung.spring.data.es.service.ArticleService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.data.elasticsearch.core.query.SearchQuery; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import java.util.List; + +import static java.util.Arrays.asList; +import static org.elasticsearch.index.query.FilterBuilders.regexpFilter; +import static org.elasticsearch.index.query.QueryBuilders.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = {Config.class}, loader = AnnotationConfigContextLoader.class) +public class ElasticSearchTest { + + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; + @Autowired + private ArticleService articleService; + + private final Author johnSmith = new Author("John Smith"); + private final Author johnDoe = new Author("John Doe"); + + @Before + public void before() { + elasticsearchTemplate.deleteIndex(Article.class); + elasticsearchTemplate.createIndex(Article.class); + + Article article = new Article("Spring Data Elasticsearch"); + article.setAuthors(asList(johnSmith, johnDoe)); + articleService.save(article); + + article = new Article("Search engines"); + article.setAuthors(asList(johnDoe)); + articleService.save(article); + + article = new Article("Second Article About Elasticsearch"); + article.setAuthors(asList(johnSmith)); + articleService.save(article); + } + + @Test + public void givenArticleService_whenSaveArticle_thenIdIsAssigned() { + List authors = asList( + new Author("John Smith"), johnDoe); + + Article article = new Article("Making Search Elastic"); + article.setAuthors(authors); + + article = articleService.save(article); + assertNotNull(article.getId()); + } + + @Test + public void givenPersistedArticles_whenSearchByAuthorsName_thenRightFound() { + + Page
articleByAuthorName = articleService.findByAuthorName(johnSmith.getName(), new PageRequest(0, 10)); + assertEquals(2L, articleByAuthorName.getTotalElements()); + } + + @Test + public void givenCustomQuery_whenSearchByAuthorsName_thenArticleIsFound() { + + Page
articleByAuthorName = articleService.findByAuthorNameUsingCustomQuery("John Smith", new PageRequest(0, 10)); + assertEquals(3L, articleByAuthorName.getTotalElements()); + } + + + @Test + public void givenPersistedArticles_whenUseRegexQuery_thenRightArticlesFound() { + + SearchQuery searchQuery = new NativeSearchQueryBuilder() + .withFilter(regexpFilter("title", ".*data.*")) + .build(); + List
articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + + assertEquals(1, articles.size()); + } + + @Test + public void givenSavedDoc_whenTitleUpdated_thenCouldFindByUpdatedTitle() { + SearchQuery searchQuery = new NativeSearchQueryBuilder() + .withQuery(fuzzyQuery("title", "serch")) + .build(); + List
articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + + assertEquals(1, articles.size()); + + Article article = articles.get(0); + final String newTitle = "Getting started with Search Engines"; + article.setTitle(newTitle); + articleService.save(article); + + assertEquals(newTitle, articleService.findOne(article.getId()).getTitle()); + } + + @Test + public void givenSavedDoc_whenDelete_thenRemovedFromIndex() { + + final String articleTitle = "Spring Data Elasticsearch"; + + SearchQuery searchQuery = new NativeSearchQueryBuilder() + .withQuery(matchQuery("title", articleTitle).minimumShouldMatch("75%")) + .build(); + List
articles = elasticsearchTemplate.queryForList(searchQuery, Article.class); + assertEquals(1, articles.size()); + final long count = articleService.count(); + + articleService.delete(articles.get(0)); + + assertEquals(count - 1, articleService.count()); + } +} diff --git a/spring-data-mongodb/.classpath b/spring-data-mongodb/.classpath new file mode 100644 index 0000000000..baf7c98131 --- /dev/null +++ b/spring-data-mongodb/.classpath @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-data-mongodb/.project b/spring-data-mongodb/.project new file mode 100644 index 0000000000..2e5a0d4bac --- /dev/null +++ b/spring-data-mongodb/.project @@ -0,0 +1,29 @@ + + + spring-data-mongodb + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/spring-data-mongodb/README.md b/spring-data-mongodb/README.md new file mode 100644 index 0000000000..d656bc897c --- /dev/null +++ b/spring-data-mongodb/README.md @@ -0,0 +1,11 @@ +========= + +## Spring Data MongoDB + + +### Relevant Articles: +- [A Guide to Queries in Spring Data MongoDB](http://www.baeldung.com/queries-in-spring-data-mongodb) +- [Spring Data MongoDB – Indexes, Annotations and Converters](http://www.baeldung.com/spring-data-mongodb-index-annotations-converter) +- [Custom Cascading in Spring Data MongoDB](http://www.baeldung.com/cascading-with-dbref-and-lifecycle-events-in-spring-data-mongodb) +- [GridFS in Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-gridfs) +- [Introduction to Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-tutorial) 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/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 index 83244a4d94..a7e75a438a 100644 --- 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 @@ -1,19 +1,22 @@ 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< String, Object> redisTemplate() { + 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 index 825248f183..acc96899ce 100644 --- 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 @@ -4,8 +4,6 @@ import java.io.Serializable; public class Student implements Serializable { - private static final long serialVersionUID = -1907106213598514113L; - public enum Gender { MALE, FEMALE } 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 index 59b3a4c5e8..9e5502f8e0 100644 --- 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 @@ -1,11 +1,13 @@ 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); 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 index 020a96f1e4..43294cae58 100644 --- 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 @@ -1,9 +1,12 @@ 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 @@ -12,28 +15,35 @@ public class StudentRepositoryImpl implements StudentRepository { private static final String KEY = "Student"; private RedisTemplate redisTemplate; + private HashOperations hashOperations; - public void setRedisTemplate(RedisTemplate redisTemplate) { + @Autowired + public StudentRepositoryImpl(RedisTemplate redisTemplate) { this.redisTemplate = redisTemplate; } + @PostConstruct + private void init() { + hashOperations = redisTemplate.opsForHash(); + } + public void saveStudent(final Student student) { - this.redisTemplate.opsForHash().put(KEY, student.getId(), student); + hashOperations.put(KEY, student.getId(), student); } public void updateStudent(final Student student) { - this.redisTemplate.opsForHash().put(KEY, student.getId(), student); + hashOperations.put(KEY, student.getId(), student); } public Student findStudent(final String id) { - return (Student) this.redisTemplate.opsForHash().get(KEY, id); + return (Student) hashOperations.get(KEY, id); } public Map findAllStudents() { - return this.redisTemplate.opsForHash().entries(KEY); + return hashOperations.entries(KEY); } public void deleteStudent(final String id) { - this.redisTemplate.opsForHash().delete(KEY, id); + hashOperations.delete(KEY, id); } } diff --git a/spring-data-redis/src/main/resources/spring-config.xml b/spring-data-redis/src/main/resources/spring-config.xml deleted file mode 100644 index 4ca240d3f1..0000000000 --- a/spring-data-redis/src/main/resources/spring-config.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file 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 index 09bc74e5cf..08540abd36 100644 --- 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 @@ -5,6 +5,7 @@ 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; @@ -14,34 +15,27 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @RunWith(SpringJUnit4ClassRunner.class) -//@ContextConfiguration(locations = { "classpath:/spring-config.xml" }) @ContextConfiguration(classes = RedisConfig.class) public class StudentRepositoryTest { - private StudentRepositoryImpl studentRepositoryImpl; - - @Before - public void setUp(){ - studentRepositoryImpl = new StudentRepositoryImpl(); - RedisConfig redisConfig = new RedisConfig(); - studentRepositoryImpl.setRedisTemplate(redisConfig.redisTemplate()); - } + @Autowired + private StudentRepository studentRepository; @Test public void whenSavingStudent_thenAvailableOnRetrieval() throws Exception { final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1); - studentRepositoryImpl.saveStudent(student); - final Student retrievedStudent = studentRepositoryImpl.findStudent(student.getId()); + 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); - studentRepositoryImpl.saveStudent(student); + studentRepository.saveStudent(student); student.setName("Richard Watson"); - studentRepositoryImpl.saveStudent(student); - final Student retrievedStudent = studentRepositoryImpl.findStudent(student.getId()); + studentRepository.saveStudent(student); + final Student retrievedStudent = studentRepository.findStudent(student.getId()); assertEquals(student.getName(), retrievedStudent.getName()); } @@ -49,18 +43,18 @@ public class StudentRepositoryTest { 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); - studentRepositoryImpl.saveStudent(engStudent); - studentRepositoryImpl.saveStudent(medStudent); - final Map retrievedStudent = studentRepositoryImpl.findAllStudents(); + 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); - studentRepositoryImpl.saveStudent(student); - studentRepositoryImpl.deleteStudent(student.getId()); - final Student retrievedStudent = studentRepositoryImpl.findStudent(student.getId()); + 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/pom.xml b/spring-exceptions/pom.xml index f4c0acec85..324b7475b3 100644 --- a/spring-exceptions/pom.xml +++ b/spring-exceptions/pom.xml @@ -105,7 +105,7 @@ junit - junit-dep + junit ${junit.version} test @@ -203,30 +203,30 @@ - 4.2.2.RELEASE - 4.0.2.RELEASE + 4.2.4.RELEASE + 4.0.3.RELEASE 3.20.0-GA 1.2 4.3.11.Final - 5.1.36 + 5.1.37 7.0.42 - 1.7.12 + 1.7.13 1.1.3 - 5.2.1.Final + 5.2.2.Final - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 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/README.md b/spring-freemarker/README.md new file mode 100644 index 0000000000..bd939d11e9 --- /dev/null +++ b/spring-freemarker/README.md @@ -0,0 +1,7 @@ +========= + +## Using FreeMarker in Spring MVC + + +### Relevant Articles: +- [Introduction to Using FreeMarker in Spring MVC](http://www.baeldung.com/freemarker-in-spring-mvc-tutorial) 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/pom.xml b/spring-hibernate3/pom.xml index 29682a97c3..d88358168f 100644 --- a/spring-hibernate3/pom.xml +++ b/spring-hibernate3/pom.xml @@ -73,7 +73,7 @@ junit - junit-dep + junit ${junit.version} test @@ -162,29 +162,29 @@ - 4.2.2.RELEASE - 4.0.2.RELEASE + 4.2.4.RELEASE + 4.0.3.RELEASE 3.20.0-GA 3.6.10.Final - 5.1.36 + 5.1.37 7.0.47 - 1.7.12 + 1.7.13 1.1.3 - 5.2.1.Final + 5.2.2.Final - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 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/README.md b/spring-hibernate4/README.md index 0d1ac1600e..4c0c6706d6 100644 --- a/spring-hibernate4/README.md +++ b/spring-hibernate4/README.md @@ -5,6 +5,9 @@ ### Relevant Articles: - [Hibernate 4 with Spring](http://www.baeldung.com/hibernate-4-spring) - [The DAO with Spring 3 and Hibernate](http://www.baeldung.com/2011/12/02/the-persistence-layer-with-spring-3-1-and-hibernate/) +- [Hibernate Pagination](http://www.baeldung.com/hibernate-pagination) +- [Sorting with Hibernate](http://www.baeldung.com/hibernate-sort) +- [Auditing with JPA, Hibernate, and Spring Data JPA](http://www.baeldung.com/database-auditing-jpa) ### Quick Start diff --git a/spring-hibernate4/pom.xml b/spring-hibernate4/pom.xml index 3b0e3b6a00..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 @@ -53,6 +77,11 @@ hibernate-validator ${hibernate-validator.version} + + javax.el + javax.el-api + 2.2.5 + @@ -77,20 +106,35 @@ ${org.springframework.version} test - + junit - junit-dep + junit ${junit.version} 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 @@ -169,24 +213,28 @@ - 4.2.2.RELEASE - 4.0.2.RELEASE - 3.20.0-GA - + 4.2.4.RELEASE + 4.0.3.RELEASE + 1.9.2.RELEASE + 3.20.0-GA + 4.3.11.Final - 5.1.36 - 7.0.42 + ${hibernate.version} + 5.1.37 + 8.0.30 + 1.1 + 2.2.4 - 1.7.12 + 1.7.13 1.1.3 - + - 5.2.1.Final + 5.2.2.Final - 18.0 + 19.0 3.4 @@ -204,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/README.md b/spring-jpa/README.md index 11df42ac52..f974c6e22c 100644 --- a/spring-jpa/README.md +++ b/spring-jpa/README.md @@ -7,3 +7,6 @@ - [Spring 3 and JPA with Hibernate](http://www.baeldung.com/2011/12/13/the-persistence-layer-with-spring-3-1-and-jpa/) - [Transactions with Spring 3 and JPA](http://www.baeldung.com/2011/12/26/transaction-configuration-with-jpa-and-spring-3-1/) - [The DAO with JPA and Spring](http://www.baeldung.com/spring-dao-jpa) +- [JPA Pagination](http://www.baeldung.com/jpa-pagination) +- [Sorting with JPA](http://www.baeldung.com/jpa-sort) +- [Spring JPA – Multiple Databases](http://www.baeldung.com/spring-data-jpa-multiple-databases) diff --git a/spring-jpa/pom.xml b/spring-jpa/pom.xml index f065fe1a81..2e8f818776 100644 --- a/spring-jpa/pom.xml +++ b/spring-jpa/pom.xml @@ -58,6 +58,11 @@ hibernate-validator ${hibernate-validator.version} + + javax.el + javax.el-api + 2.2.5 + @@ -85,7 +90,7 @@ junit - junit-dep + junit ${junit.version} test @@ -174,29 +179,29 @@ - 4.2.2.RELEASE + 4.2.4.RELEASE 4.0.2.RELEASE 3.20.0-GA 4.3.11.Final - 5.1.36 - 1.7.2.RELEASE + 5.1.37 + 1.8.2.RELEASE - 1.7.12 + 1.7.13 1.1.3 - 5.2.1.Final + 5.2.2.Final - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 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-jpa/src/main/resources/webSecurityConfig.xml b/spring-jpa/src/main/resources/webSecurityConfig.xml deleted file mode 100644 index 88af78dabc..0000000000 --- a/spring-jpa/src/main/resources/webSecurityConfig.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingTests.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingTests.java index c12dfda50c..319d36151e 100644 --- a/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingTests.java +++ b/spring-jpa/src/test/java/org/baeldung/persistence/service/FooServiceSortingTests.java @@ -15,7 +15,6 @@ import org.baeldung.persistence.model.Bar; import org.baeldung.persistence.model.Foo; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; @@ -28,9 +27,6 @@ public class FooServiceSortingTests { @PersistenceContext private EntityManager entityManager; - @Autowired - private FooService service; - // tests @Test diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/JPAMultipleDBTest.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBTest.java similarity index 98% rename from spring-jpa/src/test/java/org/baeldung/persistence/service/JPAMultipleDBTest.java rename to spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBTest.java index 4c6b02ec3d..427e182d9e 100644 --- a/spring-jpa/src/test/java/org/baeldung/persistence/service/JPAMultipleDBTest.java +++ b/spring-jpa/src/test/java/org/baeldung/persistence/service/JpaMultipleDBTest.java @@ -21,13 +21,16 @@ import org.springframework.transaction.annotation.Transactional; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { UserConfig.class, ProductConfig.class }) @TransactionConfiguration -public class JPAMultipleDBTest { +public class JpaMultipleDBTest { + @Autowired private UserRepository userRepository; @Autowired private ProductRepository productRepository; + // tests + @Test @Transactional("userTransactionManager") public void whenCreatingUser_thenCreated() { diff --git a/spring-jpa/src/test/java/org/baeldung/persistence/service/PersistenceTestSuite.java b/spring-jpa/src/test/java/org/baeldung/persistence/service/PersistenceTestSuite.java index f6c41258d4..919171de9f 100644 --- a/spring-jpa/src/test/java/org/baeldung/persistence/service/PersistenceTestSuite.java +++ b/spring-jpa/src/test/java/org/baeldung/persistence/service/PersistenceTestSuite.java @@ -8,6 +8,7 @@ import org.junit.runners.Suite; FooPaginationPersistenceIntegrationTest.class ,FooServicePersistenceIntegrationTest.class ,FooServiceSortingTests.class + ,JpaMultipleDBTest.class // manual only // ,FooServiceSortingWitNullsManualTest.class }) // @formatter:on diff --git a/spring-katharsis/README.md b/spring-katharsis/README.md new file mode 100644 index 0000000000..ec0141f41a --- /dev/null +++ b/spring-katharsis/README.md @@ -0,0 +1,6 @@ +========= + +## Java Web Application + +### Relevant Articles: +- [JSON API in a Java Web Application](http://www.baeldung.com/json-api-java-spring-web-app) diff --git a/spring-katharsis/pom.xml b/spring-katharsis/pom.xml index 554ff4e656..892aaf24f1 100644 --- a/spring-katharsis/pom.xml +++ b/spring-katharsis/pom.xml @@ -31,7 +31,7 @@ io.katharsis katharsis-servlet - 1.0.0 + ${katharsis.version} @@ -45,7 +45,7 @@ com.jayway.restassured rest-assured - 2.4.0 + ${restassured.version} test @@ -60,6 +60,8 @@ 1.8 + 1.0.0 + 2.4.0 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/README.md b/spring-mvc-java/README.md index bf76c7e1d4..e5264b0370 100644 --- a/spring-mvc-java/README.md +++ b/spring-mvc-java/README.md @@ -4,3 +4,7 @@ ### Relevant Articles: +- [Spring Bean Annotations](http://www.baeldung.com/spring-bean-annotations) +- [Introduction to Pointcut Expressions in Spring](http://www.baeldung.com/spring-aop-pointcut-tutorial) +- [Introduction to Advice Types in Spring](http://www.baeldung.com/spring-aop-advice-tutorial) +- [A Guide to the ViewResolver in Spring MVC](http://www.baeldung.com/spring-mvc-view-resolver-tutorial) diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml index 772bbbb219..d9a578cb8c 100644 --- a/spring-mvc-java/pom.xml +++ b/spring-mvc-java/pom.xml @@ -3,14 +3,10 @@ org.baeldung spring-mvc-java 0.1-SNAPSHOT - spring-mvc-java war - - - org.springframework spring-web @@ -21,64 +17,53 @@ spring-webmvc ${org.springframework.version} - - javax.servlet javax.servlet-api 3.0.1 provided - javax.servlet jstl 1.2 runtime - org.springframework spring-aop ${org.springframework.version} - org.aspectj aspectjrt ${aspectj.version} - org.aspectj aspectjweaver ${aspectj.version} - org.slf4j slf4j-api ${org.slf4j.version} - org.slf4j slf4j-log4j12 ${org.slf4j.version} - - junit - junit-dep + junit ${junit.version} test - org.hamcrest hamcrest-core @@ -91,21 +76,29 @@ ${org.hamcrest.version} test - org.mockito mockito-core ${mockito.version} test - org.springframework spring-test ${org.springframework.version} test - + + + org.thymeleaf + thymeleaf-spring4 + ${thymeleaf.version} + + + org.thymeleaf + thymeleaf + ${thymeleaf.version} + @@ -118,7 +111,6 @@ - org.apache.maven.plugins maven-compiler-plugin @@ -129,6 +121,11 @@ + + maven-resources-plugin + 2.7 + + org.apache.maven.plugins maven-war-plugin @@ -137,7 +134,6 @@ false - org.apache.maven.plugins maven-surefire-plugin @@ -151,7 +147,6 @@ - org.codehaus.cargo cargo-maven2-plugin @@ -172,50 +167,40 @@ - - - + - 4.2.2.RELEASE - 4.0.2.RELEASE - + 4.2.4.RELEASE + 4.0.3.RELEASE + 2.1.4.RELEASE 4.3.11.Final - 5.1.36 - + 5.1.37 - 1.7.12 + 1.7.13 1.1.3 - - 5.2.1.Final - + 5.2.2.Final - 18.0 + 19.0 3.4 - 1.3 - 4.11 + 4.12 1.10.19 - 4.4.1 4.5 - 2.4.1 - 3.3 2.6 2.18.1 2.7 - 1.4.15 - + 1.4.17 1.8.7 - + \ No newline at end of file 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 new file mode 100644 index 0000000000..c59c4f060a --- /dev/null +++ b/spring-mvc-java/src/main/java/org/baeldung/aop/LoggingAspect.java @@ -0,0 +1,54 @@ +package org.baeldung.aop; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.logging.Logger; + +@Component +@Aspect +public class LoggingAspect { + + private static Logger logger = Logger.getLogger(LoggingAspect.class.getName()); + + private ThreadLocal sdf = new ThreadLocal() { + @Override + protected SimpleDateFormat initialValue() { + return new SimpleDateFormat("[yyyy-mm-dd hh:mm:ss:SSS]"); + } + }; + + @Pointcut("@target(org.springframework.stereotype.Repository)") + public void repositoryMethods() { + } + + @Pointcut("@annotation(org.baeldung.aop.annotations.Loggable)") + public void loggableMethods() { + } + + @Pointcut("@args(org.baeldung.aop.annotations.Entity)") + public void methodsAcceptingEntities() { + } + + @Before("repositoryMethods()") + public void logMethodCall(JoinPoint jp) { + String methodName = jp.getSignature().getName(); + logger.info(sdf.get().format(new Date()) + methodName); + } + + @Before("loggableMethods()") + public void logMethod(JoinPoint jp) { + String methodName = jp.getSignature().getName(); + logger.info("Executing method: " + methodName); + } + + @Before("methodsAcceptingEntities()") + public void logMethodAcceptionEntityAnnotatedBean(JoinPoint jp) { + logger.info("Accepting beans with @Entity annotation: " + jp.getArgs()[0]); + } +} 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 12d6bc4e69..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 new file mode 100644 index 0000000000..324605dab1 --- /dev/null +++ b/spring-mvc-java/src/main/java/org/baeldung/aop/PublishingAspect.java @@ -0,0 +1,39 @@ +package org.baeldung.aop; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.baeldung.events.FooCreationEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +@Component +@Aspect +public class PublishingAspect { + + private ApplicationEventPublisher eventPublisher; + + @Autowired + public void setEventPublisher(ApplicationEventPublisher eventPublisher) { + this.eventPublisher = eventPublisher; + } + + @Pointcut("@target(org.springframework.stereotype.Repository)") + public void repositoryMethods() { + } + + @Pointcut("execution(* *..create*(Long,..))") + public void firstLongParamMethods() { + } + + @Pointcut("repositoryMethods() && firstLongParamMethods()") + public void entityCreationMethods() { + } + + @AfterReturning(value = "entityCreationMethods()", returning = "entity") + public void logMethodCall(JoinPoint jp, Object entity) throws Throwable { + eventPublisher.publishEvent(new FooCreationEvent(entity)); + } +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Entity.java b/spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Entity.java new file mode 100644 index 0000000000..f964c3979e --- /dev/null +++ b/spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Entity.java @@ -0,0 +1,11 @@ +package org.baeldung.aop.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface Entity { +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Loggable.java b/spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Loggable.java new file mode 100644 index 0000000000..ef2863957f --- /dev/null +++ b/spring-mvc-java/src/main/java/org/baeldung/aop/annotations/Loggable.java @@ -0,0 +1,11 @@ +package org.baeldung.aop.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Loggable { +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/dao/FooDao.java b/spring-mvc-java/src/main/java/org/baeldung/dao/FooDao.java index fbd7f4c717..f204440b2d 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/dao/FooDao.java +++ b/spring-mvc-java/src/main/java/org/baeldung/dao/FooDao.java @@ -1,10 +1,22 @@ package org.baeldung.dao; +import org.baeldung.aop.annotations.Loggable; +import org.baeldung.model.Foo; import org.springframework.stereotype.Repository; @Repository public class FooDao { + public String findById(Long id) { return "Bazz"; } + + @Loggable + public Foo create(Long id, String name) { + return new Foo(id, name); + } + + public Foo merge(Foo foo) { + return foo; + } } diff --git a/spring-mvc-java/src/main/java/org/baeldung/dialect/CustomDialect.java b/spring-mvc-java/src/main/java/org/baeldung/dialect/CustomDialect.java new file mode 100644 index 0000000000..e6d1ad6b74 --- /dev/null +++ b/spring-mvc-java/src/main/java/org/baeldung/dialect/CustomDialect.java @@ -0,0 +1,24 @@ +package org.baeldung.dialect; + +import java.util.HashSet; +import java.util.Set; + +import org.baeldung.processor.NameProcessor; +import org.thymeleaf.dialect.AbstractDialect; +import org.thymeleaf.processor.IProcessor; + +public class CustomDialect extends AbstractDialect { + + @Override + public String getPrefix() { + return "custom"; + } + + @Override + public Set getProcessors() { + final Set processors = new HashSet(); + processors.add(new NameProcessor()); + return processors; + } + +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEvent.java b/spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEvent.java new file mode 100644 index 0000000000..af11f3a4be --- /dev/null +++ b/spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEvent.java @@ -0,0 +1,10 @@ +package org.baeldung.events; + +import org.springframework.context.ApplicationEvent; + +public class FooCreationEvent extends ApplicationEvent { + + public FooCreationEvent(Object source) { + super(source); + } +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEventListener.java b/spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEventListener.java new file mode 100644 index 0000000000..35dcfd2bc3 --- /dev/null +++ b/spring-mvc-java/src/main/java/org/baeldung/events/FooCreationEventListener.java @@ -0,0 +1,17 @@ +package org.baeldung.events; + +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import java.util.logging.Logger; + +@Component +public class FooCreationEventListener implements ApplicationListener { + + private static Logger logger = Logger.getLogger(FooCreationEventListener.class.getName()); + + @Override + public void onApplicationEvent(FooCreationEvent event) { + logger.info("Created foo instance: " + event.getSource().toString()); + } +} 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 new file mode 100644 index 0000000000..87bd7132e6 --- /dev/null +++ b/spring-mvc-java/src/main/java/org/baeldung/model/Foo.java @@ -0,0 +1,19 @@ +package org.baeldung.model; + +import org.baeldung.aop.annotations.Entity; + +@Entity +public class Foo { + private Long id; + private String name; + + public Foo(Long id, String name) { + this.id = id; + this.name = name; + } + + @Override + public String toString() { + return "Foo{" + "id=" + id + ", name='" + name + '\'' + '}'; + } +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/model/User.java b/spring-mvc-java/src/main/java/org/baeldung/model/User.java new file mode 100644 index 0000000000..df549cd21d --- /dev/null +++ b/spring-mvc-java/src/main/java/org/baeldung/model/User.java @@ -0,0 +1,32 @@ +package org.baeldung.model; + +public class User { + private String firstname; + private String lastname; + private String emailId; + + public String getFirstname() { + return firstname; + } + + public void setFirstname(final String firstname) { + this.firstname = firstname; + } + + public String getLastname() { + return lastname; + } + + public void setLastname(final String lastname) { + this.lastname = lastname; + } + + public String getEmailId() { + return emailId; + } + + public void setEmailId(final String emailId) { + this.emailId = emailId; + } + +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/processor/NameProcessor.java b/spring-mvc-java/src/main/java/org/baeldung/processor/NameProcessor.java new file mode 100644 index 0000000000..df9a4da7f0 --- /dev/null +++ b/spring-mvc-java/src/main/java/org/baeldung/processor/NameProcessor.java @@ -0,0 +1,23 @@ +package org.baeldung.processor; + +import org.thymeleaf.Arguments; +import org.thymeleaf.dom.Element; +import org.thymeleaf.processor.attr.AbstractTextChildModifierAttrProcessor; + +public class NameProcessor extends AbstractTextChildModifierAttrProcessor { + + public NameProcessor() { + super("name"); + } + + @Override + protected String getText(final Arguments arguements, final Element elements, final String attributeName) { + return "Hello, " + elements.getAttributeValue(attributeName) + "!"; + } + + @Override + public int getPrecedence() { + return 1000; + } + +} diff --git a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/ClientWebConfig.java b/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/ClientWebConfig.java index 945c1794fb..db57b4716b 100644 --- a/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/ClientWebConfig.java +++ b/spring-mvc-java/src/main/java/org/baeldung/spring/web/config/ClientWebConfig.java @@ -1,13 +1,25 @@ package org.baeldung.spring.web.config; +import java.util.HashSet; +import java.util.Set; + +import org.baeldung.dialect.CustomDialect; +import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Description; +import org.springframework.context.support.ResourceBundleMessageSource; 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; import org.springframework.web.servlet.view.JstlView; +import org.thymeleaf.dialect.IDialect; +import org.thymeleaf.spring4.SpringTemplateEngine; +import org.thymeleaf.spring4.view.ThymeleafViewResolver; +import org.thymeleaf.templateresolver.ServletContextTemplateResolver; @EnableWebMvc @Configuration @@ -26,14 +38,56 @@ public class ClientWebConfig extends WebMvcConfigurerAdapter { registry.addViewController("/sample.html"); } + @Bean + public ViewResolver thymeleafViewResolver() { + final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); + viewResolver.setTemplateEngine(templateEngine()); + viewResolver.setOrder(1); + return viewResolver; + } + @Bean public ViewResolver viewResolver() { final InternalResourceViewResolver bean = new InternalResourceViewResolver(); - bean.setViewClass(JstlView.class); bean.setPrefix("/WEB-INF/view/"); bean.setSuffix(".jsp"); - + bean.setOrder(0); return bean; } + + @Bean + @Description("Thymeleaf template resolver serving HTML 5") + public ServletContextTemplateResolver templateResolver() { + final ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(); + templateResolver.setPrefix("/WEB-INF/templates/"); + templateResolver.setSuffix(".html"); + templateResolver.setTemplateMode("HTML5"); + return templateResolver; + } + + @Bean + @Description("Thymeleaf template engine with Spring integration") + public SpringTemplateEngine templateEngine() { + final SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.setTemplateResolver(templateResolver()); + final Set dialects = new HashSet<>(); + dialects.add(new CustomDialect()); + templateEngine.setAdditionalDialects(dialects); + return templateEngine; + } + + @Bean + @Description("Spring message resolver") + public MessageSource messageSource() { + final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); + messageSource.setBasename("messages"); + return messageSource; + } + + @Override + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); + } + } \ No newline at end of file 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 new file mode 100644 index 0000000000..da39a36adf --- /dev/null +++ b/spring-mvc-java/src/main/java/org/baeldung/web/controller/UserController.java @@ -0,0 +1,31 @@ +package org.baeldung.web.controller; + +import org.baeldung.model.User; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +@Controller +@RequestMapping("/") +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"; + } + + @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"; + } + +} diff --git a/spring-mvc-java/src/main/resources/messages_en.properties b/spring-mvc-java/src/main/resources/messages_en.properties new file mode 100644 index 0000000000..549024372b --- /dev/null +++ b/spring-mvc-java/src/main/resources/messages_en.properties @@ -0,0 +1 @@ +welcome.text=Hello \ No newline at end of file diff --git a/spring-mvc-java/src/main/resources/org/baeldung/aop/beans.xml b/spring-mvc-java/src/main/resources/org/baeldung/aop/beans.xml new file mode 100644 index 0000000000..17c63e39e4 --- /dev/null +++ b/spring-mvc-java/src/main/resources/org/baeldung/aop/beans.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file 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/main/webapp/WEB-INF/templates/footer.html b/spring-mvc-java/src/main/webapp/WEB-INF/templates/footer.html new file mode 100644 index 0000000000..f72d553303 --- /dev/null +++ b/spring-mvc-java/src/main/webapp/WEB-INF/templates/footer.html @@ -0,0 +1,6 @@ + + + +
© 2013 Footer
+ + \ No newline at end of file diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/templates/hello.html b/spring-mvc-java/src/main/webapp/WEB-INF/templates/hello.html new file mode 100644 index 0000000000..1eddd85166 --- /dev/null +++ b/spring-mvc-java/src/main/webapp/WEB-INF/templates/hello.html @@ -0,0 +1,14 @@ + + + + + + + Hi + John ! + Test +
© 2013 The Static + Templates
+ + \ No newline at end of file diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/templates/index.html b/spring-mvc-java/src/main/webapp/WEB-INF/templates/index.html new file mode 100644 index 0000000000..9b4159c193 --- /dev/null +++ b/spring-mvc-java/src/main/webapp/WEB-INF/templates/index.html @@ -0,0 +1,36 @@ + + + + +Thymeleaf Spring Example + + + Hello John! +

+
Please confirm your details
+

+
+ + + + + + + + + + + + + + + + +
Firstname :
Lastname :
EmailId :
+
+ + \ 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 new file mode 100644 index 0000000000..b1c9867e41 --- /dev/null +++ b/spring-mvc-java/src/test/java/org/baeldung/aop/AopLoggingTest.java @@ -0,0 +1,82 @@ +package org.baeldung.aop; + +import org.baeldung.config.TestConfig; +import org.baeldung.dao.FooDao; +import org.baeldung.model.Foo; +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.support.AnnotationConfigContextLoader; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import java.util.regex.Pattern; + +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.core.IsCollectionContaining.hasItem; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) +public class AopLoggingTest { + + @Before + public void setUp() { + messages = new ArrayList<>(); + + logEventHandler = new Handler() { + @Override + public void publish(LogRecord record) { + messages.add(record.getMessage()); + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }; + + Logger logger = Logger.getLogger(LoggingAspect.class.getName()); + logger.addHandler(logEventHandler); + } + + @Autowired + private FooDao dao; + + private Handler logEventHandler; + + private List messages; + + @Test + public void givenLoggingAspect_whenCallDaoMethod_thenBeforeAdviceIsCalled() { + dao.findById(1L); + assertThat(messages, hasSize(1)); + + String logMessage = messages.get(0); + Pattern pattern = Pattern.compile("^\\[\\d{4}\\-\\d{2}\\-\\d{2} \\d{2}:\\d{2}:\\d{2}:\\d{3}\\]findById$"); + assertTrue(pattern.matcher(logMessage).matches()); + } + + @Test + public void givenLoggingAspect_whenCallLoggableAnnotatedMethod_thenMethodIsLogged() { + dao.create(42L, "baz"); + assertThat(messages, hasItem("Executing method: create")); + } + + @Test + public void givenLoggingAspect_whenCallMethodAcceptingAnnotatedArgument_thenArgumentIsLogged() { + Foo foo = new Foo(42L, "baz"); + dao.merge(foo); + assertThat(messages, hasItem("Accepting beans with @Entity annotation: " + foo)); + } +} 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 new file mode 100644 index 0000000000..e691dbd32e --- /dev/null +++ b/spring-mvc-java/src/test/java/org/baeldung/aop/AopPublishingTest.java @@ -0,0 +1,66 @@ +package org.baeldung.aop; + +import org.baeldung.config.TestConfig; +import org.baeldung.dao.FooDao; +import org.baeldung.events.FooCreationEventListener; +import org.baeldung.model.Foo; +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.support.AnnotationConfigContextLoader; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import java.util.regex.Pattern; + +import static org.junit.Assert.assertTrue; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) +public class AopPublishingTest { + + @Before + public void setUp() { + logEventHandler = new Handler() { + @Override + public void publish(LogRecord record) { + messages.add(record.getMessage()); + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }; + + messages = new ArrayList<>(); + } + + @Autowired + private FooDao dao; + + private Handler logEventHandler; + + private List messages; + + @Test + public void givenPublishingAspect_whenCallCreate_thenCreationEventIsPublished() { + Logger logger = Logger.getLogger(FooCreationEventListener.class.getName()); + logger.addHandler(logEventHandler); + + dao.create(1L, "Bar"); + + String logMessage = messages.get(0); + 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/aop/AopXmlConfigPerformanceTest.java b/spring-mvc-java/src/test/java/org/baeldung/aop/AopXmlConfigPerformanceTest.java new file mode 100644 index 0000000000..7ef25d743c --- /dev/null +++ b/spring-mvc-java/src/test/java/org/baeldung/aop/AopXmlConfigPerformanceTest.java @@ -0,0 +1,67 @@ +package org.baeldung.aop; + +import org.baeldung.dao.FooDao; +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.ArrayList; +import java.util.List; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import java.util.regex.Pattern; + +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.Matchers.hasSize; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/org/baeldung/aop/beans.xml") +public class AopXmlConfigPerformanceTest { + + @Before + public void setUp() { + logEventHandler = new Handler() { + @Override + public void publish(LogRecord record) { + messages.add(record.getMessage()); + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }; + + messages = new ArrayList<>(); + } + + @Autowired + private FooDao dao; + + private Handler logEventHandler; + + private List messages; + + @Test + public void givenPerformanceAspect_whenCallDaoMethod_thenPerformanceMeasurementAdviceIsCalled() { + Logger logger = Logger.getLogger(PerformanceAspect.class.getName()); + logger.addHandler(logEventHandler); + + final String entity = dao.findById(1L); + assertThat(entity, notNullValue()); + assertThat(messages, hasSize(1)); + + String logMessage = messages.get(0); + Pattern pattern = Pattern.compile("Execution of findById took \\d+ ms"); + 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 60786a108c..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"}) +@ComponentScan(basePackages = { "org.baeldung.dao", "org.baeldung.aop", "org.baeldung.events" }) @EnableAspectJAutoProxy public class TestConfig { } diff --git a/spring-mvc-no-xml/pom.xml b/spring-mvc-no-xml/pom.xml index ecb159f82e..da71a699db 100644 --- a/spring-mvc-no-xml/pom.xml +++ b/spring-mvc-no-xml/pom.xml @@ -67,7 +67,7 @@ junit - junit-dep + junit ${junit.version} test @@ -144,15 +144,15 @@ - 4.2.2.RELEASE + 4.2.4.RELEASE - 1.7.12 + 1.7.13 1.1.3 1.3 - 4.11 + 4.12 1.10.19 4.4.1 diff --git a/spring-mvc-xml/README.md b/spring-mvc-xml/README.md index 908e21d4bf..2409ec8174 100644 --- a/spring-mvc-xml/README.md +++ b/spring-mvc-xml/README.md @@ -7,3 +7,4 @@ ### Relevant Articles: - [Spring MVC Tutorial](http://www.baeldung.com/spring-mvc-tutorial) - [Servlet Session Timeout](http://www.baeldung.com/servlet-session-timeout) +- [Basic Forms with Spring MVC](http://www.baeldung.com/spring-mvc-form-tutorial) diff --git a/spring-mvc-xml/pom.xml b/spring-mvc-xml/pom.xml index 378d2be339..896d744e99 100644 --- a/spring-mvc-xml/pom.xml +++ b/spring-mvc-xml/pom.xml @@ -73,7 +73,7 @@ junit - junit-dep + junit ${junit.version} test @@ -146,15 +146,15 @@ - 4.2.2.RELEASE + 4.2.4.RELEASE - 1.7.12 + 1.7.13 1.1.3 1.3 - 4.11 + 4.12 1.10.19 4.4.1 diff --git a/spring-openid/.classpath b/spring-openid/.classpath new file mode 100644 index 0000000000..0cad5db2d0 --- /dev/null +++ b/spring-openid/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-openid/.project b/spring-openid/.project new file mode 100644 index 0000000000..81874eb896 --- /dev/null +++ b/spring-openid/.project @@ -0,0 +1,48 @@ + + + spring-openid + + + + + + 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-openid/pom.xml b/spring-openid/pom.xml new file mode 100644 index 0000000000..641fe93a09 --- /dev/null +++ b/spring-openid/pom.xml @@ -0,0 +1,68 @@ + + + 4.0.0 + + org.baeldung + spring-openid + 0.0.1-SNAPSHOT + war + + spring-openid + Spring OpenID sample project + + + org.springframework.boot + spring-boot-starter-parent + 1.3.2.RELEASE + + + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + + org.springframework.security.oauth + spring-security-oauth2 + + + + org.springframework.security + spring-security-jwt + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + UTF-8 + 1.8 + + diff --git a/spring-openid/src/main/java/org/baeldung/config/GoogleOpenIdConnectConfig.java b/spring-openid/src/main/java/org/baeldung/config/GoogleOpenIdConnectConfig.java new file mode 100644 index 0000000000..8e9c6e974e --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/config/GoogleOpenIdConnectConfig.java @@ -0,0 +1,51 @@ +package org.baeldung.config; + +import java.util.Arrays; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.OAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; + +@Configuration +@EnableOAuth2Client +public class GoogleOpenIdConnectConfig { + @Value("${google.clientId}") + private String clientId; + + @Value("${google.clientSecret}") + private String clientSecret; + + @Value("${google.accessTokenUri}") + private String accessTokenUri; + + @Value("${google.userAuthorizationUri}") + private String userAuthorizationUri; + + @Value("${google.redirectUri}") + private String redirectUri; + + @Bean + public OAuth2ProtectedResourceDetails googleOpenId() { + final AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); + details.setClientId(clientId); + details.setClientSecret(clientSecret); + details.setAccessTokenUri(accessTokenUri); + details.setUserAuthorizationUri(userAuthorizationUri); + details.setScope(Arrays.asList("openid", "email")); + details.setPreEstablishedRedirectUri(redirectUri); + details.setUseCurrentUri(false); + return details; + } + + @Bean + public OAuth2RestTemplate googleOpenIdTemplate(final OAuth2ClientContext clientContext) { + final OAuth2RestTemplate template = new OAuth2RestTemplate(googleOpenId(), clientContext); + return template; + } + +} diff --git a/spring-openid/src/main/java/org/baeldung/config/HomeController.java b/spring-openid/src/main/java/org/baeldung/config/HomeController.java new file mode 100644 index 0000000000..f0a5378019 --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/config/HomeController.java @@ -0,0 +1,22 @@ +package org.baeldung.config; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class HomeController { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @RequestMapping("/") + @ResponseBody + public final String home() { + final String username = SecurityContextHolder.getContext().getAuthentication().getName(); + logger.info(username); + return "Welcome, " + username; + } + +} diff --git a/spring-openid/src/main/java/org/baeldung/config/SecurityConfig.java b/spring-openid/src/main/java/org/baeldung/config/SecurityConfig.java new file mode 100644 index 0000000000..d929bfd631 --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/config/SecurityConfig.java @@ -0,0 +1,49 @@ +package org.baeldung.config; + +import org.baeldung.security.OpenIdConnectFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +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; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; +import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; +import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + @Autowired + private OAuth2RestTemplate restTemplate; + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Bean + public OpenIdConnectFilter myFilter() { + final OpenIdConnectFilter filter = new OpenIdConnectFilter("/google-login"); + filter.setRestTemplate(restTemplate); + return filter; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .addFilterAfter(new OAuth2ClientContextFilter(), AbstractPreAuthenticatedProcessingFilter.class) + .addFilterAfter(myFilter(), OAuth2ClientContextFilter.class) + .httpBasic().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/google-login")) + .and() + .authorizeRequests() + // .antMatchers("/","/index*").permitAll() + .anyRequest().authenticated() + ; + + // @formatter:on + } +} \ No newline at end of file diff --git a/spring-openid/src/main/java/org/baeldung/config/SpringOpenidApplication.java b/spring-openid/src/main/java/org/baeldung/config/SpringOpenidApplication.java new file mode 100644 index 0000000000..608e8a6819 --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/config/SpringOpenidApplication.java @@ -0,0 +1,13 @@ +package org.baeldung.config; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringOpenidApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringOpenidApplication.class, args); + } + +} diff --git a/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectFilter.java b/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectFilter.java new file mode 100644 index 0000000000..c0970ab3cf --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectFilter.java @@ -0,0 +1,71 @@ +package org.baeldung.security; + +import java.io.IOException; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.jwt.Jwt; +import org.springframework.security.jwt.JwtHelper; +import org.springframework.security.oauth2.client.OAuth2RestOperations; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class OpenIdConnectFilter extends AbstractAuthenticationProcessingFilter { + public OAuth2RestOperations restTemplate; + + public OpenIdConnectFilter(String defaultFilterProcessesUrl) { + super(defaultFilterProcessesUrl); + setAuthenticationManager(new NoopAuthenticationManager()); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { + + OAuth2AccessToken accessToken; + try { + accessToken = restTemplate.getAccessToken(); + } catch (final OAuth2Exception e) { + throw new BadCredentialsException("Could not obtain access token", e); + } + try { + final String idToken = accessToken.getAdditionalInformation().get("id_token").toString(); + final Jwt tokenDecoded = JwtHelper.decode(idToken); + System.out.println("===== : " + tokenDecoded.getClaims()); + + final Map authInfo = new ObjectMapper().readValue(tokenDecoded.getClaims(), Map.class); + + final OpenIdConnectUserDetails user = new OpenIdConnectUserDetails(authInfo, accessToken); + return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); + } catch (final InvalidTokenException e) { + throw new BadCredentialsException("Could not obtain user details from token", e); + } + + } + + public void setRestTemplate(OAuth2RestTemplate restTemplate2) { + restTemplate = restTemplate2; + + } + + private static class NoopAuthenticationManager implements AuthenticationManager { + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + throw new UnsupportedOperationException("No authentication should be done with this AuthenticationManager"); + } + + } +} diff --git a/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectUserDetails.java b/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectUserDetails.java new file mode 100644 index 0000000000..f0d91fdc27 --- /dev/null +++ b/spring-openid/src/main/java/org/baeldung/security/OpenIdConnectUserDetails.java @@ -0,0 +1,81 @@ +package org.baeldung.security; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.common.OAuth2AccessToken; + +public class OpenIdConnectUserDetails implements UserDetails { + + private static final long serialVersionUID = 1L; + + private String userId; + private String username; + private OAuth2AccessToken token; + + public OpenIdConnectUserDetails(Map userInfo, OAuth2AccessToken token) { + this.userId = userInfo.get("sub"); + this.username = userInfo.get("email"); + this.token = token; + } + + @Override + public String getUsername() { + return username; + } + + @Override + public Collection getAuthorities() { + return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public OAuth2AccessToken getToken() { + return token; + } + + public void setToken(OAuth2AccessToken token) { + this.token = token; + } + + public void setUsername(String username) { + this.username = username; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + +} diff --git a/spring-openid/src/main/resources/application.properties b/spring-openid/src/main/resources/application.properties new file mode 100644 index 0000000000..fa567a164c --- /dev/null +++ b/spring-openid/src/main/resources/application.properties @@ -0,0 +1,6 @@ +server.port=8081 +google.clientId=497324626536-d6fphsh1qpl2o6j2j66nukajrfqc0rtq.apps.googleusercontent.com +google.clientSecret=vtueZycMsrRjjCjnY6JzbEZT +google.accessTokenUri=https://www.googleapis.com/oauth2/v3/token +google.userAuthorizationUri=https://accounts.google.com/o/oauth2/auth +google.redirectUri=http://localhost:8081/google-login \ No newline at end of file diff --git a/spring-rest/README.md b/spring-rest/README.md index 3b93b06d66..9d373962c4 100644 --- a/spring-rest/README.md +++ b/spring-rest/README.md @@ -7,3 +7,4 @@ - [Spring @RequestMapping](http://www.baeldung.com/spring-requestmapping) - [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) - [Redirect in Spring](http://www.baeldung.com/spring-redirect-and-forward) +- [Returning Custom Status Codes from Spring Controllers](http://www.baeldung.com/spring-mvc-controller-custom-http-status-code) diff --git a/spring-rest/pom.xml b/spring-rest/pom.xml index 7bc0905542..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} @@ -128,7 +125,7 @@ junit - junit-dep + junit ${junit.version} test @@ -229,27 +226,26 @@ - 4.2.2.RELEASE - 4.0.2.RELEASE + 4.0.3.RELEASE 4.3.11.Final - 5.1.36 + 5.1.37 - 2.5.1 + 2.5.5 - 5.2.1.Final + 5.2.2.Final - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 @@ -258,7 +254,7 @@ 2.4.1 - 1.7.12 + 1.7.13 1.1.3 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-basic-auth/pom.xml b/spring-security-basic-auth/pom.xml index 72914dd0d5..1e15cd5b53 100644 --- a/spring-security-basic-auth/pom.xml +++ b/spring-security-basic-auth/pom.xml @@ -82,14 +82,14 @@ javax.servlet javax.servlet-api - 3.0.1 + ${javax.servlet.version} provided javax.servlet jstl - 1.2 + ${jstl.version} runtime @@ -98,7 +98,7 @@ com.google.guava guava - 14.0.1 + ${guava.version} @@ -130,7 +130,7 @@ junit - junit-dep + junit ${junit.version} test @@ -225,27 +225,29 @@ - 4.2.2.RELEASE - 4.0.2.RELEASE + 4.2.4.RELEASE + 4.0.3.RELEASE 4.3.11.Final - 5.1.36 + 5.1.37 - 1.7.12 + 1.7.13 1.1.3 - 5.2.1.Final - + 5.2.2.Final + 1.2 + 3.0.1 + - 18.0 + 19.0 3.4 1.3 - 4.11 + 4.12 1.10.19 4.4.1 diff --git a/spring-security-login-and-registration/.classpath b/spring-security-login-and-registration/.classpath index 91f27076be..26981b6dd7 100644 --- a/spring-security-login-and-registration/.classpath +++ b/spring-security-login-and-registration/.classpath @@ -23,7 +23,7 @@ - + diff --git a/spring-security-rest-full/.externalToolBuilders/org.hibernate.eclipse.console.hibernateBuilder.launch b/spring-security-login-and-registration/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch similarity index 87% rename from spring-security-rest-full/.externalToolBuilders/org.hibernate.eclipse.console.hibernateBuilder.launch rename to spring-security-login-and-registration/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch index 9bc0284d26..627021fb96 100644 --- a/spring-security-rest-full/.externalToolBuilders/org.hibernate.eclipse.console.hibernateBuilder.launch +++ b/spring-security-login-and-registration/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch @@ -1,7 +1,7 @@ - + diff --git a/spring-security-login-and-registration/.project b/spring-security-login-and-registration/.project index 2c3e86ed06..4a27f224a4 100644 --- a/spring-security-login-and-registration/.project +++ b/spring-security-login-and-registration/.project @@ -6,8 +6,13 @@ - org.eclipse.wst.jsdt.core.javascriptValidator + org.eclipse.ui.externaltools.ExternalToolBuilder + full,incremental, + + LaunchConfigHandle + <project>/.externalToolBuilders/org.eclipse.wst.jsdt.core.javascriptValidator.launch + @@ -25,16 +30,6 @@ - - org.jboss.tools.jst.web.kb.kbbuilder - - - - - org.hibernate.eclipse.console.hibernateBuilder - - - org.eclipse.wst.validation.validationbuilder diff --git a/spring-security-login-and-registration/README.md b/spring-security-login-and-registration/README.md index 1c5b16d6f6..07fb21bfff 100644 --- a/spring-security-login-and-registration/README.md +++ b/spring-security-login-and-registration/README.md @@ -5,8 +5,16 @@ ### Relevant Articles: - [Spring Security Registration Tutorial](http://www.baeldung.com/spring-security-registration) - - +- [The Registration Process With Spring Security](http://www.baeldung.com/registration-with-spring-mvc-and-spring-security) +- [Registration – Activate a New Account by Email](http://www.baeldung.com/registration-verify-user-by-email) +- [Registration with Spring Security – Password Encoding](http://www.baeldung.com/spring-security-registration-password-encoding-bcrypt) +- [Spring Security – Roles and Privileges](http://www.baeldung.com/role-and-privilege-for-spring-security-registration) +- [Prevent Brute Force Authentication Attempts with Spring Security](http://www.baeldung.com/spring-security-block-brute-force-authentication-attempts) +- [Spring Security – Reset Your Password](http://www.baeldung.com/spring-security-registration-i-forgot-my-password) +- [Spring Security Registration – Resend Verification Email](http://www.baeldung.com/spring-security-registration-verification-email) +- [The Registration API becomes RESTful](http://www.baeldung.com/registration-restful-api) +- [Registration – Password Strength and Rules](http://www.baeldung.com/registration-password-strength-and-rules) +- [Updating your Password](http://www.baeldung.com/updating-your-password/) ### Build the Project ``` diff --git a/spring-security-login-and-registration/pom.xml b/spring-security-login-and-registration/pom.xml index df7e639660..bcbe9371e2 100644 --- a/spring-security-login-and-registration/pom.xml +++ b/spring-security-login-and-registration/pom.xml @@ -9,67 +9,108 @@ spring-security-login-and-registration war - - org.springframework.boot - spring-boot-starter-parent - 1.2.6.RELEASE - + - + + - org.springframework.boot - spring-boot-starter-web - - - org.springframework - spring-context-support + org.springframework.security + spring-security-web + ${org.springframework.security.version} org.springframework.security spring-security-config + ${org.springframework.security.version} + + + org.springframework.security + spring-security-taglibs + ${org.springframework.security.version} - + + - org.springframework.boot - spring-boot-starter-tomcat - provided + org.springframework + spring-core + ${org.springframework.version} + + + commons-logging + commons-logging + + - org.apache.tomcat.embed - tomcat-embed-websocket - provided + org.springframework + spring-context + ${org.springframework.version} + + + org.springframework + spring-context-support + ${org.springframework.version} + + + org.springframework + spring-jdbc + ${org.springframework.version} + + + org.springframework + spring-beans + ${org.springframework.version} + + + org.springframework + spring-aop + ${org.springframework.version} + + + org.springframework + spring-tx + ${org.springframework.version} + + + org.springframework + spring-expression + ${org.springframework.version} + + + + org.springframework + spring-web + ${org.springframework.version} + + + org.springframework + spring-webmvc + ${org.springframework.version} javax.servlet javax.servlet-api + ${javax.servlet.version} + provided - - javax.servlet.jsp - javax.servlet.jsp-api - ${javax.servlet.jsp-api.version} - + javax.servlet jstl + ${jstl.version} + runtime - - org.springframework.security - spring-security-taglibs - - - javax.el - el-api - 2.2 - + org.springframework spring-test + ${org.springframework.version} test @@ -77,17 +118,19 @@ org.passay passay - 1.0 + ${passay.version} org.springframework.data spring-data-jpa + ${spring-data-jpa.version} org.hibernate hibernate-entitymanager + ${hibernate.version} @@ -98,25 +141,29 @@ org.hibernate hibernate-validator + ${hibernate-validator.version} mysql mysql-connector-java + ${mysql-connector-java.version} commons-dbcp commons-dbcp + ${commons-dbcp.version} com.fasterxml.jackson.core jackson-databind + ${jackson.version} javax.mail mail - 1.4.7 + ${javax.mail.version} com.google.guava @@ -128,32 +175,51 @@ org.slf4j slf4j-api + ${org.slf4j.version} ch.qos.logback logback-classic + ${logback.version} + org.slf4j jcl-over-slf4j + ${org.slf4j.version} org.slf4j log4j-over-slf4j + ${org.slf4j.version} junit junit + ${junit.version} test - + + + org.hamcrest + hamcrest-core + ${org.hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + + com.jayway.restassured rest-assured - 2.4.0 + ${rest-assured.version} test @@ -163,6 +229,11 @@ + + javax.el + el-api + 2.2 + @@ -181,8 +252,8 @@ maven-compiler-plugin ${maven-compiler-plugin.version} - ${java-version} - ${java-version} + 1.8 + 1.8 @@ -192,33 +263,11 @@ ${maven-war-plugin.version} - - org.codehaus.cargo - cargo-maven2-plugin - ${cargo-maven2-plugin.version} - - true - - tomcat8x - embedded - - - - - - - 8081 - - - - - org.apache.maven.plugins maven-surefire-plugin ${maven-surefire-plugin.version} - true **/*IntegrationTest.java **/*LiveTest.java @@ -229,32 +278,73 @@ + + org.codehaus.cargo + cargo-maven2-plugin + ${cargo-maven2-plugin.version} + + true + + jetty8x + embedded + + + + + + + 8082 + + + + + + - 1.7 - 4.1.6.RELEASE - 4.0.2.RELEASE + 1.8 + + + 4.2.4.RELEASE + 4.0.3.RELEASE + + 4.3.11.Final + 5.2.2.Final + 5.1.37 + 1.9.2.RELEASE + + - 1.7.12 + 1.7.13 1.1.3 2.3.2-b01 - + 3.0.1 + 1.2 + 1 - 1.8.0.RELEASE + 1.8.2.RELEASE - 18.0 + 19.0 + 1.3 + 4.12 + 1.0 + 2.4.0 + 1.4.7 + 2.6.4 + 1.4 + - 1.4.16 + 1.4.17 3.3 2.6 2.18.1 diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/security/CustomAuthenticationFailureHandler.java b/spring-security-login-and-registration/src/main/java/org/baeldung/security/CustomAuthenticationFailureHandler.java new file mode 100644 index 0000000000..94440f8a89 --- /dev/null +++ b/spring-security-login-and-registration/src/main/java/org/baeldung/security/CustomAuthenticationFailureHandler.java @@ -0,0 +1,47 @@ +package org.baeldung.security; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.WebAttributes; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.LocaleResolver; + +@Component("authenticationFailureHandler") +public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { + + @Autowired + private MessageSource messages; + + @Autowired + private LocaleResolver localeResolver; + + @Override + public void onAuthenticationFailure(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException exception) throws IOException, ServletException { + setDefaultFailureUrl("/login.html?error=true"); + + super.onAuthenticationFailure(request, response, exception); + + final Locale locale = localeResolver.resolveLocale(request); + + String errorMessage = messages.getMessage("message.badCredentials", null, locale); + + if (exception.getMessage().equalsIgnoreCase("User is disabled")) { + errorMessage = messages.getMessage("auth.message.disabled", null, locale); + } else if (exception.getMessage().equalsIgnoreCase("User account has expired")) { + errorMessage = messages.getMessage("auth.message.expired", null, locale); + } else if (exception.getMessage().equalsIgnoreCase("blocked")) { + errorMessage = messages.getMessage("auth.message.blocked", null, locale); + } + + request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, errorMessage); + } +} \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/security/MyUserDetailsService.java b/spring-security-login-and-registration/src/main/java/org/baeldung/security/MyUserDetailsService.java index d9c3e586b1..d4b77878be 100644 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/security/MyUserDetailsService.java +++ b/spring-security-login-and-registration/src/main/java/org/baeldung/security/MyUserDetailsService.java @@ -1,13 +1,11 @@ package org.baeldung.security; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; import javax.servlet.http.HttpServletRequest; -import org.baeldung.persistence.dao.RoleRepository; import org.baeldung.persistence.dao.UserRepository; import org.baeldung.persistence.model.Privilege; import org.baeldung.persistence.model.Role; @@ -28,9 +26,6 @@ public class MyUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; - @Autowired - private RoleRepository roleRepository; - @Autowired private LoginAttemptService loginAttemptService; @@ -45,7 +40,7 @@ public class MyUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(final String email) throws UsernameNotFoundException { - final String ip = request.getRemoteAddr(); + final String ip = getClientIP(); if (loginAttemptService.isBlocked(ip)) { throw new RuntimeException("blocked"); } @@ -53,7 +48,7 @@ public class MyUserDetailsService implements UserDetailsService { try { final User user = userRepository.findByEmail(email); if (user == null) { - return new org.springframework.security.core.userdetails.User(" ", " ", true, true, true, true, getAuthorities(Arrays.asList(roleRepository.findByName("ROLE_USER")))); + throw new UsernameNotFoundException("No user found with username: " + email); } return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), user.isEnabled(), true, true, true, getAuthorities(user.getRoles())); @@ -88,4 +83,11 @@ public class MyUserDetailsService implements UserDetailsService { return authorities; } + private String getClientIP() { + final String xfHeader = request.getHeader("X-Forwarded-For"); + if (xfHeader == null) { + return request.getRemoteAddr(); + } + return xfHeader.split(",")[0]; + } } diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/MvcConfig.java b/spring-security-login-and-registration/src/main/java/org/baeldung/spring/MvcConfig.java index 56141d8f33..1234cde0d0 100644 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/MvcConfig.java +++ b/spring-security-login-and-registration/src/main/java/org/baeldung/spring/MvcConfig.java @@ -35,7 +35,7 @@ public class MvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(final ViewControllerRegistry registry) { super.addViewControllers(registry); - registry.addViewController("/login.html"); + registry.addViewController("/login"); registry.addViewController("/registration.html"); registry.addViewController("/logout.html"); registry.addViewController("/homepage.html"); diff --git a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/SecSecurityConfig.java b/spring-security-login-and-registration/src/main/java/org/baeldung/spring/SecSecurityConfig.java index 814ed92b33..9ae8f6e78b 100644 --- a/spring-security-login-and-registration/src/main/java/org/baeldung/spring/SecSecurityConfig.java +++ b/spring-security-login-and-registration/src/main/java/org/baeldung/spring/SecSecurityConfig.java @@ -13,10 +13,12 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; @Configuration @ComponentScan(basePackages = { "org.baeldung.security" }) +// @ImportResource({ "classpath:webSecurityConfig.xml" }) @EnableWebSecurity public class SecSecurityConfig extends WebSecurityConfigurerAdapter { @@ -26,6 +28,9 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private AuthenticationSuccessHandler myAuthenticationSuccessHandler; + @Autowired + private AuthenticationFailureHandler authenticationFailureHandler; + public SecSecurityConfig() { super(); } @@ -46,7 +51,7 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { http .csrf().disable() .authorizeRequests() - .antMatchers("/j_spring_security_check*","/login*", "/logout*", "/signin/**", "/signup/**", + .antMatchers("/login*","/login*", "/logout*", "/signin/**", "/signup/**", "/user/registration*", "/regitrationConfirm*", "/expiredAccount*", "/registration*", "/badUser*", "/user/resendRegistrationToken*" ,"/forgetPassword*", "/user/resetPassword*", "/user/changePassword*", "/emailError*", "/resources/**","/old/user/registration*","/successRegister*").permitAll() @@ -54,13 +59,11 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { .anyRequest().authenticated() .and() .formLogin() - .loginPage("/login.html") - .loginProcessingUrl("/j_spring_security_check") + .loginPage("/login") .defaultSuccessUrl("/homepage.html") - .failureUrl("/login.html?error=true") + .failureUrl("/login?error=true") .successHandler(myAuthenticationSuccessHandler) - .usernameParameter("j_username") - .passwordParameter("j_password") + .failureHandler(authenticationFailureHandler) .permitAll() .and() .sessionManagement() @@ -69,7 +72,6 @@ public class SecSecurityConfig extends WebSecurityConfigurerAdapter { .and() .logout() .invalidateHttpSession(false) - .logoutUrl("/j_spring_security_logout") .logoutSuccessUrl("/logout.html?logSucc=true") .deleteCookies("JSESSIONID") .permitAll(); 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-login-and-registration/src/main/resources/webSecurityConfig-basic.xml b/spring-security-login-and-registration/src/main/resources/webSecurityConfig-basic.xml new file mode 100644 index 0000000000..bf85a09b62 --- /dev/null +++ b/spring-security-login-and-registration/src/main/resources/webSecurityConfig-basic.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/resources/webSecurityConfig.xml b/spring-security-login-and-registration/src/main/resources/webSecurityConfig.xml index 677b0864c4..4e67a1200f 100644 --- a/spring-security-login-and-registration/src/main/resources/webSecurityConfig.xml +++ b/spring-security-login-and-registration/src/main/resources/webSecurityConfig.xml @@ -1,9 +1,10 @@ @@ -27,14 +28,30 @@ - - - + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/admin.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/admin.jsp index db3d8f20ba..ad0a8231ad 100644 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/admin.jsp +++ b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/admin.jsp @@ -15,7 +15,7 @@ "> diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/changePassword.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/changePassword.jsp index c5ff23287d..88836e96f5 100644 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/changePassword.jsp +++ b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/changePassword.jsp @@ -17,7 +17,7 @@ diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/console.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/console.jsp index 1cf661af87..e06cdd39f0 100644 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/console.jsp +++ b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/console.jsp @@ -13,7 +13,7 @@ "> diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/home.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/home.jsp index f8db1632f6..027f583d61 100644 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/home.jsp +++ b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/home.jsp @@ -14,7 +14,7 @@ diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/homepage.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/homepage.jsp index 86cac0152f..af931ac66f 100644 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/homepage.jsp +++ b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/homepage.jsp @@ -15,7 +15,7 @@ "> diff --git a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/login.jsp b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/login.jsp index d1be07060a..a71fe9dc3a 100644 --- a/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/login.jsp +++ b/spring-security-login-and-registration/src/main/webapp/WEB-INF/view/login.jsp @@ -7,34 +7,7 @@ <%@ page session="true"%> - - - -
- -
-
- -
- -
-
- -
- -
-
- -
- - -
-
-
-
+ @@ -42,20 +15,20 @@ <spring:message code="label.pages.home.title"></spring:message> + + + + + +
+

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