diff --git a/.travis.yml b/.travis.yml index 7da572edf9..6063fbf3e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ install: travis_wait 40 mvn -q clean install -Dgib.enabled=true jdk: - oraclejdk8 -sudo: false addons: apt: packages: diff --git a/core-java-9/compile-modules.sh b/core-java-9/compile-modules.sh new file mode 100644 index 0000000000..4c9521de75 --- /dev/null +++ b/core-java-9/compile-modules.sh @@ -0,0 +1 @@ +javac -d mods --module-source-path src/modules $(find src/modules -name "*.java") \ No newline at end of file diff --git a/core-java-9/compile-student-client.bat b/core-java-9/compile-student-client.bat new file mode 100644 index 0000000000..72b2774480 --- /dev/null +++ b/core-java-9/compile-student-client.bat @@ -0,0 +1,3 @@ +javac --module-path mods -d mods/com.baeldung.student.client^ + src/modules/com.baeldung.student.client/module-info.java^ + src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java \ No newline at end of file diff --git a/core-java-9/compile-student-model.bat b/core-java-9/compile-student-model.bat new file mode 100644 index 0000000000..902756c274 --- /dev/null +++ b/core-java-9/compile-student-model.bat @@ -0,0 +1,2 @@ +javac -d mods/com.baeldung.student.model src/modules/com.baeldung.student.model/module-info.java^ + src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java \ No newline at end of file diff --git a/core-java-9/compile-student-service-dbimpl.bat b/core-java-9/compile-student-service-dbimpl.bat new file mode 100644 index 0000000000..bd1cfb7cfe --- /dev/null +++ b/core-java-9/compile-student-service-dbimpl.bat @@ -0,0 +1,3 @@ +javac --module-path mods -d mods/com.baeldung.student.service.dbimpl^ + src/modules/com.baeldung.student.service.dbimpl/module-info.java^ + src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java \ No newline at end of file diff --git a/core-java-9/compile-student-service.bat b/core-java-9/compile-student-service.bat new file mode 100644 index 0000000000..2892b237d1 --- /dev/null +++ b/core-java-9/compile-student-service.bat @@ -0,0 +1,3 @@ +javac --module-path mods -d mods/com.baeldung.student.service^ + src/modules/com.baeldung.student.service/module-info.java^ + src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java \ No newline at end of file diff --git a/core-java-9/run-student-client.bat b/core-java-9/run-student-client.bat new file mode 100644 index 0000000000..2b78a26ec4 --- /dev/null +++ b/core-java-9/run-student-client.bat @@ -0,0 +1 @@ +java --module-path mods -m com.baeldung.student.client/com.baeldung.student.client.StudentClient \ No newline at end of file diff --git a/core-java-9/run-student-client.sh b/core-java-9/run-student-client.sh new file mode 100644 index 0000000000..2b78a26ec4 --- /dev/null +++ b/core-java-9/run-student-client.sh @@ -0,0 +1 @@ +java --module-path mods -m com.baeldung.student.client/com.baeldung.student.client.StudentClient \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java b/core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java new file mode 100644 index 0000000000..e6fce9163f --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java @@ -0,0 +1,16 @@ +package com.baeldung.student.client; + +import com.baeldung.student.service.StudentService; +import com.baeldung.student.service.dbimpl.StudentDbService; +import com.baeldung.student.model.Student; + +public class StudentClient { + + public static void main(String[] args) { + StudentService service = new StudentDbService(); + service.create(new Student()); + service.read("17SS0001"); + service.update(new Student()); + service.delete("17SS0001"); + } +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.client/module-info.java b/core-java-9/src/modules/com.baeldung.student.client/module-info.java new file mode 100644 index 0000000000..7ef7b430fc --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.client/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.student.client{ + requires com.baeldung.student.service.dbimpl; +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java b/core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java new file mode 100644 index 0000000000..d7f8f69107 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java @@ -0,0 +1,15 @@ +package com.baeldung.student.model; + +import java.util.Date; + +public class Student { + private String registrationId; + + public String getRegistrationId() { + return registrationId; + } + + public void setRegistrationId(String registrationId) { + this.registrationId = registrationId; + } +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.model/module-info.java b/core-java-9/src/modules/com.baeldung.student.model/module-info.java new file mode 100644 index 0000000000..3bdab058d4 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.model/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.student.model{ + exports com.baeldung.student.model; +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java b/core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java new file mode 100644 index 0000000000..2519da085b --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java @@ -0,0 +1,30 @@ +package com.baeldung.student.service.dbimpl; + +import com.baeldung.student.service.StudentService; +import com.baeldung.student.model.Student; +import java.util.logging.*; + +public class StudentDbService implements StudentService { + + private static Logger logger = Logger.getLogger("StudentDbService"); + + public String create(Student student) { + logger.log(Level.INFO, "Creating student in DB..."); + return student.getRegistrationId(); + } + + public Student read(String registrationId) { + logger.log(Level.INFO, "Reading student from DB..."); + return new Student(); + } + + public Student update(Student student) { + logger.log(Level.INFO, "Updating sutdent in DB..."); + return student; + } + + public String delete(String registrationId) { + logger.log(Level.INFO, "Deleteing sutdent in DB..."); + return registrationId; + } +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java b/core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java new file mode 100644 index 0000000000..96a453ea6b --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java @@ -0,0 +1,5 @@ +module com.baeldung.student.service.dbimpl{ + requires transitive com.baeldung.student.service; + exports com.baeldung.student.service.dbimpl; + requires java.logging; +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java b/core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java new file mode 100644 index 0000000000..6076bf12e3 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java @@ -0,0 +1,14 @@ +package com.baeldung.student.service; + +import com.baeldung.student.model.Student; + +public interface StudentService { + + public String create(Student student); + + public Student read(String registrationId); + + public Student update(Student student); + + public String delete(String registrationId); +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.service/module-info.java b/core-java-9/src/modules/com.baeldung.student.service/module-info.java new file mode 100644 index 0000000000..5de9e58348 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.service/module-info.java @@ -0,0 +1,4 @@ +module com.baeldung.student.service{ + requires transitive com.baeldung.student.model; + exports com.baeldung.student.service; +} \ No newline at end of file diff --git a/core-java/src/main/java/com/baeldung/list/flattennestedlist/FlattenNestedList.java b/core-java/src/main/java/com/baeldung/list/flattennestedlist/FlattenNestedList.java deleted file mode 100644 index 11ee66560b..0000000000 --- a/core-java/src/main/java/com/baeldung/list/flattennestedlist/FlattenNestedList.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.list.flattennestedlist; - -import java.util.ArrayList; -import java.util.List; - -public class FlattenNestedList { - - public List flattenListOfLists(List> lol) { - - // flatten the list - List ls = new ArrayList<>(); - lol.forEach((k) -> ls.addAll(k)); - - return ls; - } - -} diff --git a/core-java/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListTest.java b/core-java/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListTest.java index 09bfdae9a5..cf9334954b 100644 --- a/core-java/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListTest.java +++ b/core-java/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListTest.java @@ -1,52 +1,64 @@ package com.baeldung.list.flattennestedlist; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class FlattenNestedListTest { - private static final Logger LOGGER = LoggerFactory.getLogger(FlattenNestedListTest.class); - private FlattenNestedList flol; - - @Before - public void setup() { - flol = new FlattenNestedList(); - } - @Test - public void givenListOfListOfString_flattenNestedList() { - - // create the list to flatten + public void givenListOfListOfString_flattenNestedList1() { + // given List ls1 = Arrays.asList("one:one", "one:two", "one:three"); List ls2 = Arrays.asList("two:one", "two:two", "two:three"); List ls3 = Arrays.asList("three:one", "three:two", "three:three"); - List> lol = new ArrayList<>(); - lol.addAll(Arrays.asList(ls1, ls2, ls3)); - - // show nested list - LOGGER.debug("\nNested list: "); - lol.forEach((nl) -> LOGGER.debug(nl + "")); + List> list = Arrays.asList(ls1, ls2, ls3); - // flatten it - List ls = flol.flattenListOfLists(lol); + // when + List ls = flattenListOfListsImperatively(list); + // then assertNotNull(ls); assertTrue(ls.size() == 9); - - // show flattened list - LOGGER.debug("\nFlattened list:"); - ls.forEach((l) -> LOGGER.debug(l)); + //TODO content assertion + } + @Test + public void givenListOfListOfString_flattenNestedList2() { + // given + List ls1 = Arrays.asList("one:one", "one:two", "one:three"); + List ls2 = Arrays.asList("two:one", "two:two", "two:three"); + List ls3 = Arrays.asList("three:one", "three:two", "three:three"); + + List> list = Arrays.asList(ls1, ls2, ls3); + + // when + List ls = flattenListOfListsStream(list); + + // then + assertNotNull(ls); + assertTrue(ls.size() == 9); + //TODO content assertion + } + + public List flattenListOfListsImperatively(List> list) { + List ls = new ArrayList<>(); + list.forEach(ls::addAll); + return ls; + } + + public List flattenListOfListsStream(List> list) { + return list.stream() + .flatMap(Collection::stream) + .collect(Collectors.toList()); } } diff --git a/guice/README.md b/guice/README.md new file mode 100644 index 0000000000..d1bd1ff883 --- /dev/null +++ b/guice/README.md @@ -0,0 +1,4 @@ +## Google Guice Tutorials Project + +### Relevant Articles +- [Guide to Google Guice](http://www.baeldung.com/guice) diff --git a/libraries/pom.xml b/libraries/pom.xml index c89efa3f66..eaae539872 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -23,7 +23,7 @@ - + cglib @@ -51,6 +51,11 @@ javatuples ${javatuples.version} + + org.javassist + javassist + ${javaassist.version} + org.assertj @@ -65,6 +70,7 @@ 4.12 1.9.2 1.2 + 3.21.0-GA 3.6.2 diff --git a/libraries/src/main/java/com/baeldung/javasisst/Point.java b/libraries/src/main/java/com/baeldung/javasisst/Point.java new file mode 100644 index 0000000000..7e5c1cedd5 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/javasisst/Point.java @@ -0,0 +1,17 @@ +package com.baeldung.javasisst; + + +public class Point { + public int x = 0; + public int y = 0; + + public Point(int x, int y) { + this.x = x; + this.y = y; + } + + public void move(int x, int y) { + this.x = x; + this.y = y; + } +} diff --git a/libraries/src/main/java/com/baeldung/javasisst/ThreeDimensionalPoint.java b/libraries/src/main/java/com/baeldung/javasisst/ThreeDimensionalPoint.java new file mode 100644 index 0000000000..fb24d4b85d --- /dev/null +++ b/libraries/src/main/java/com/baeldung/javasisst/ThreeDimensionalPoint.java @@ -0,0 +1,19 @@ +package com.baeldung.javasisst; + + +public class ThreeDimensionalPoint { + public int x = 0; + public int y = 0; + public int z = 0; + + public ThreeDimensionalPoint(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + public void move(int x, int y) { + this.x = x; + this.y = y; + } +} diff --git a/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java new file mode 100644 index 0000000000..da5ae02c56 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java @@ -0,0 +1,119 @@ +package com.baeldung.javassist; + + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.NotFoundException; +import javassist.bytecode.*; +import org.junit.Test; + +import java.io.DataOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class JavasisstTest { + @Test + public void givenJavasisstAPI_whenConstructClass_thenGenerateAClassFile() throws CannotCompileException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException { + //given + String classNameWithPackage = "com.baeldung.JavassistGeneratedClass"; + ClassFile cf = new ClassFile(false, classNameWithPackage, null); + cf.setInterfaces(new String[]{"java.lang.Cloneable"}); + + FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I"); + f.setAccessFlags(AccessFlag.PUBLIC); + cf.addField(f); + + //when + String className = "JavassistGeneratedClass.class"; + cf.write(new DataOutputStream(new FileOutputStream(className))); + + //then + ClassPool classPool = ClassPool.getDefault(); + Field[] fields = classPool.makeClass(cf).toClass().getFields(); + assertEquals(fields[0].getName(), "id"); + + String classContent = new String(Files.readAllBytes(Paths.get(className))); + assertTrue(classContent.contains("java/lang/Cloneable")); + } + + @Test + public void givenJavaClass_whenLoadAtByJavassist_thenTraversWholeClass() throws NotFoundException, CannotCompileException, BadBytecode { + //given + ClassPool cp = ClassPool.getDefault(); + ClassFile cf = cp.get("com.baeldung.javasisst.Point").getClassFile(); + MethodInfo minfo = cf.getMethod("move"); + CodeAttribute ca = minfo.getCodeAttribute(); + CodeIterator ci = ca.iterator(); + + //when + List operations = new LinkedList<>(); + while (ci.hasNext()) { + int index = ci.next(); + int op = ci.byteAt(index); + operations.add(Mnemonic.OPCODE[op]); + } + + //then + assertEquals(operations, + Arrays.asList("aload_0", "iload_1", "putfield", "aload_0", "iload_2", "putfield", "return")); + + } + + @Test + public void givenTableOfInstructions_whenAddNewInstruction_thenShouldConstructProperSequence() throws NotFoundException, BadBytecode, CannotCompileException, IllegalAccessException, InstantiationException { + //given + ClassFile cf = ClassPool.getDefault().get("com.baeldung.javasisst.ThreeDimensionalPoint").getClassFile(); + + //when + FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I"); + f.setAccessFlags(AccessFlag.PUBLIC); + cf.addField(f); + + + ClassPool classPool = ClassPool.getDefault(); + Field[] fields = classPool.makeClass(cf).toClass().getFields(); + List fieldsList = Stream.of(fields).map(Field::getName).collect(Collectors.toList()); + assertTrue(fieldsList.contains("id")); + + } + + @Test + public void givenLoadedClass_whenAddConstructorToClass_shouldCreateClassWithConstructor() throws NotFoundException, CannotCompileException, BadBytecode { + //given + ClassFile cf = ClassPool.getDefault().get("com.baeldung.javasisst.Point").getClassFile(); + Bytecode code = new Bytecode(cf.getConstPool()); + code.addAload(0); + code.addInvokespecial("java/lang/Object", MethodInfo.nameInit, "()V"); + code.addReturn(null); + + //when + MethodInfo minfo = new MethodInfo(cf.getConstPool(), MethodInfo.nameInit, "()V"); + minfo.setCodeAttribute(code.toCodeAttribute()); + cf.addMethod(minfo); + + //then + CodeIterator ci = code.toCodeAttribute().iterator(); + List operations = new LinkedList<>(); + while (ci.hasNext()) { + int index = ci.next(); + int op = ci.byteAt(index); + operations.add(Mnemonic.OPCODE[op]); + } + + assertEquals(operations, + Arrays.asList("aload_0", "invokespecial", "return")); + + + } +} diff --git a/ratpack/build.gradle b/ratpack/build.gradle index 29d9633531..aeddd5f9f9 100644 --- a/ratpack/build.gradle +++ b/ratpack/build.gradle @@ -4,6 +4,7 @@ buildscript { } dependencies { classpath "io.ratpack:ratpack-gradle:1.4.5" + classpath "com.h2database:h2:1.4.193" } } @@ -19,6 +20,8 @@ repositories { } dependencies { + compile ratpack.dependency('hikari') + compile 'com.h2database:h2:1.4.193' testCompile 'junit:junit:4.11' runtime "org.slf4j:slf4j-simple:1.7.21" } diff --git a/ratpack/pom.xml b/ratpack/pom.xml index 0290a25d2b..bb606b9b11 100644 --- a/ratpack/pom.xml +++ b/ratpack/pom.xml @@ -15,22 +15,41 @@ - - io.ratpack - ratpack-core - 1.4.5 - - - io.ratpack - ratpack-test - 1.4.5 - - - junit - junit - 4.12 - test - + + io.ratpack + ratpack-core + 1.4.5 + + + io.ratpack + ratpack-hikari + 1.4.5 + + + io.ratpack + ratpack-test + 1.4.5 + + + com.h2database + h2 + 1.4.193 + + + junit + junit + 4.12 + test + + + ${project.artifactId} + + + src/main/resources + + + + diff --git a/ratpack/src/main/java/com/baeldung/Application.java b/ratpack/src/main/java/com/baeldung/Application.java index 3a5bf54d00..94709e88e9 100644 --- a/ratpack/src/main/java/com/baeldung/Application.java +++ b/ratpack/src/main/java/com/baeldung/Application.java @@ -1,22 +1,48 @@ package com.baeldung; +import java.util.ArrayList; +import java.util.List; + +import com.baeldung.filter.RequestValidatorFilter; +import com.baeldung.model.Employee; + +import ratpack.guice.Guice; +import ratpack.hikari.HikariModule; +import ratpack.http.MutableHeaders; +import ratpack.jackson.Jackson; import ratpack.http.MutableHeaders; import ratpack.server.RatpackServer; public class Application { - public static void main(String... args) throws Exception { - RatpackServer.start(server -> server.handlers(chain -> chain.all(ctx -> { - MutableHeaders headers = ctx.getResponse().getHeaders(); - headers.set("Access-Control-Allow-Origin", "*"); - headers.set("Accept-Language", "en-us"); - headers.set("Accept-Charset", "UTF-8"); - ctx.next(); - }) - .get(ctx -> ctx.render("Welcome to baeldung ratpack!!!")) - .get(":name", ctx -> ctx.render("Hello " + ctx.getPathTokens().get("name") + "!!!")) - .post(":amount", ctx -> ctx.render(" Amount $" + ctx.getPathTokens().get("amount") + " added successfully !!!")) - )); + public static void main(String[] args) throws Exception { + + List employees = new ArrayList(); + employees.add(new Employee(1L, "Mr", "John Doe")); + employees.add(new Employee(2L, "Mr", "White Snow")); + + + RatpackServer.start( + server -> server.registry(Guice.registry(bindings -> bindings.module(HikariModule.class, config -> { + config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource"); + config.addDataSourceProperty("URL", + "jdbc:h2:mem:baeldung;INIT=RUNSCRIPT FROM 'classpath:/DDL.sql'"); + }))).handlers(chain -> chain + .all( + // ctx -> { + // MutableHeaders headers = + // ctx.getResponse().getHeaders(); + // headers.set("Access-Control-Allow-Origin","*"); + // headers.set("Accept-Language", "en-us"); + // headers.set("Accept-Charset", "UTF-8"); + // ctx.next(); + // } + new RequestValidatorFilter()) + .get(ctx -> ctx.render("Welcome to baeldung ratpack!!!")) + .get("data/employees", ctx -> ctx.render(Jackson.json(employees))) + .get(":name", ctx -> ctx.render("Hello " + ctx.getPathTokens().get("name") + "!!!")) + .post(":amount", ctx -> ctx + .render(" Amount $" + ctx.getPathTokens().get("amount") + " added successfully !!!")))); } } diff --git a/ratpack/src/main/java/com/baeldung/filter/RequestValidatorFilter.java b/ratpack/src/main/java/com/baeldung/filter/RequestValidatorFilter.java new file mode 100644 index 0000000000..0a8b77aa71 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/filter/RequestValidatorFilter.java @@ -0,0 +1,16 @@ +package com.baeldung.filter; + +import ratpack.handling.Context; +import ratpack.handling.Handler; +import ratpack.http.MutableHeaders; + +public class RequestValidatorFilter implements Handler { + + @Override + public void handle(Context ctx) throws Exception { + MutableHeaders headers = ctx.getResponse().getHeaders(); + headers.set("Access-Control-Allow-Origin", "*"); + ctx.next(); + } + +} diff --git a/ratpack/src/main/java/com/baeldung/model/Employee.java b/ratpack/src/main/java/com/baeldung/model/Employee.java new file mode 100644 index 0000000000..c983d8b769 --- /dev/null +++ b/ratpack/src/main/java/com/baeldung/model/Employee.java @@ -0,0 +1,44 @@ +package com.baeldung.model; + +import java.io.Serializable; + +public class Employee implements Serializable { + + private static final long serialVersionUID = 3077867088762010705L; + + private Long id; + private String title; + private String name; + + public Employee(Long id, String title, String name) { + super(); + this.id = id; + this.title = title; + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/ratpack/src/main/resources/DDL.sql b/ratpack/src/main/resources/DDL.sql new file mode 100644 index 0000000000..af8709ee75 --- /dev/null +++ b/ratpack/src/main/resources/DDL.sql @@ -0,0 +1,6 @@ +DROP TABLE IF EXISTS employee; +CREATE TABLE employee ( + id bigint auto_increment primary key, + title varchar(255), + name varchar(255) +) \ No newline at end of file diff --git a/ratpack/src/test/java/com/baeldung/ApplicationTest.java b/ratpack/src/test/java/com/baeldung/ApplicationTest.java index f04a51f2bb..0333441928 100644 --- a/ratpack/src/test/java/com/baeldung/ApplicationTest.java +++ b/ratpack/src/test/java/com/baeldung/ApplicationTest.java @@ -4,10 +4,17 @@ import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import com.baeldung.model.Employee; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + import ratpack.test.MainClassApplicationUnderTest; import static org.junit.Assert.assertEquals; +import java.util.ArrayList; +import java.util.List; + @RunWith(JUnit4.class) public class ApplicationTest { @@ -23,6 +30,16 @@ public class ApplicationTest { assertEquals("Hello dummybot!!!", appUnderTest.getHttpClient().getText("/dummybot")); } + @Test + public void givenUrl_getListOfEmployee() throws JsonProcessingException { + List employees = new ArrayList(); + ObjectMapper mapper = new ObjectMapper(); + employees.add(new Employee(1L, "Mr", "John Doe")); + employees.add(new Employee(2L, "Mr", "White Snow")); + + assertEquals(mapper.writeValueAsString(employees), appUnderTest.getHttpClient().getText("/data/employees")); + } + @After public void shutdown() { appUnderTest.close(); diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml index 7a305322a6..f087617709 100644 --- a/spring-boot/pom.xml +++ b/spring-boot/pom.xml @@ -12,7 +12,7 @@ org.springframework.boot spring-boot-starter-parent - 1.5.1.RELEASE + 1.5.2.RELEASE diff --git a/spring-boot/src/main/java/com/baeldung/internationalization/InternationalizationApp.java b/spring-boot/src/main/java/com/baeldung/internationalization/InternationalizationApp.java new file mode 100644 index 0000000000..c92d1c32e6 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/internationalization/InternationalizationApp.java @@ -0,0 +1,15 @@ +package com.baeldung.internationalization; + +import javax.annotation.security.RolesAllowed; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class InternationalizationApp { + @RolesAllowed("*") + public static void main(String[] args) { + System.setProperty("security.basic.enabled", "false"); + SpringApplication.run(InternationalizationApp.class, args); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/internationalization/config/MvcConfig.java b/spring-boot/src/main/java/com/baeldung/internationalization/config/MvcConfig.java new file mode 100644 index 0000000000..59f7fd3ba5 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/internationalization/config/MvcConfig.java @@ -0,0 +1,38 @@ +package com.baeldung.internationalization.config; + +import java.util.Locale; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; +import org.springframework.web.servlet.i18n.SessionLocaleResolver; + +@Configuration +@EnableWebMvc +@ComponentScan(basePackages = "com.baeldung.internationalization.config") +public class MvcConfig extends WebMvcConfigurerAdapter { + + @Bean + public LocaleResolver localeResolver() { + SessionLocaleResolver slr = new SessionLocaleResolver(); + slr.setDefaultLocale(Locale.US); + return slr; + } + + @Bean + public LocaleChangeInterceptor localeChangeInterceptor() { + LocaleChangeInterceptor lci = new LocaleChangeInterceptor(); + lci.setParamName("lang"); + return lci; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(localeChangeInterceptor()); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/internationalization/config/PageController.java b/spring-boot/src/main/java/com/baeldung/internationalization/config/PageController.java new file mode 100644 index 0000000000..96a534b853 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/internationalization/config/PageController.java @@ -0,0 +1,14 @@ +package com.baeldung.internationalization.config; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class PageController { + + @GetMapping("/international") + public String getInternationalPage() { + return "international"; + } + +} diff --git a/spring-boot/src/main/resources/application.properties b/spring-boot/src/main/resources/application.properties index 8c6549f53d..1ffc95849d 100644 --- a/spring-boot/src/main/resources/application.properties +++ b/spring-boot/src/main/resources/application.properties @@ -33,3 +33,11 @@ logging.level.org.springframework=INFO #Servlet Configuration servlet.name=dispatcherExample servlet.mapping=/dispatcherExampleURL + +#banner.charset=UTF-8 +#banner.location=classpath:banner.txt +#banner.image.location=classpath:banner.gif +#banner.image.width= //TODO +#banner.image.height= //TODO +#banner.image.margin= //TODO +#banner.image.invert= //TODO \ No newline at end of file diff --git a/spring-boot/src/main/resources/banner.txt b/spring-boot/src/main/resources/banner.txt new file mode 100644 index 0000000000..abfa666eb6 --- /dev/null +++ b/spring-boot/src/main/resources/banner.txt @@ -0,0 +1,14 @@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@#@@@@@########@@@@@@@@@@@@@@@@@@@@@@@@...@@@@@@@@@:..@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@#. @@@@@* *@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@#o @@@@@* @@@@@* @@@:*.*@@@@@@@: *8@@@ @@@@&:.#@. @o**@@@@**:@o*o@@:.:@@@@@:.o#@&*:@@@@ +@@@@@@@@@@@@* @@@@@* 8888 8@ @@@8 #@o 8@# .@ @@* :. @* @@@@ @. : &@ ** .@@@@ +@@@@@@@@@@. @ o@@@@@* *@@@o::& .* 8@@@@. @@ 8@@@@. @* @@@@ @. @@@& * @@@@# .@@@@ +@@@@@@@@@& @ @@@@@@* @@@@@@ 8 @@@@ .. o&&&&&&& @@ #@@@@. @* @@@@ @. @@@# * @@@@@ .@@@@ +@@@@@@@@@ @@o @@@@@@@* oooo* 8 @@@& @* @@@ # 88. 88. *& o#: @. @@@# *@ &#& .@@@@ +@@@@@@@@# @@@8 @@@@@@@* .*@@@#. *@@ @@@& :#@@@o .@@: *&@8 @o o@@: @. @@@# *@@#. :8# .@@@@ +@@@@@@@@@ @@@@ &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@# o@@@@ @@@@@ +@@@@@& &@@@@ 8@@@@@@@@@8&8@@@@@#8#@@@o8@#&@@o&@@@&@@8@@&@@@@88@@8#@8&@@##@@@@@@#8@@#8@@88@@@@@ *@@@@@@@ +@@@# #@@@@#. @@@@@@@@@@@@@8@@8#o@&#@@@@o.@o*@@*.@@@.@&:8o8*@@@8&@@#@@@8@@@@8@#@@@8&@@@@@@#@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \ No newline at end of file diff --git a/spring-boot/src/main/resources/messages.properties b/spring-boot/src/main/resources/messages.properties new file mode 100644 index 0000000000..e4dbc44c3f --- /dev/null +++ b/spring-boot/src/main/resources/messages.properties @@ -0,0 +1,4 @@ +greeting=Hello! Welcome to our website! +lang.change=Change the language +lang.eng=English +lang.fr=French \ No newline at end of file diff --git a/spring-boot/src/main/resources/messages_fr.properties b/spring-boot/src/main/resources/messages_fr.properties new file mode 100644 index 0000000000..ac5853717d --- /dev/null +++ b/spring-boot/src/main/resources/messages_fr.properties @@ -0,0 +1,4 @@ +greeting=Bonjour! Bienvenue sur notre site! +lang.change=Changez la langue +lang.eng=Anglais +lang.fr=Francais \ No newline at end of file diff --git a/spring-boot/src/main/resources/templates/international.html b/spring-boot/src/main/resources/templates/international.html new file mode 100644 index 0000000000..a2a5fbb591 --- /dev/null +++ b/spring-boot/src/main/resources/templates/international.html @@ -0,0 +1,29 @@ + + + + +Home + + + + +

+ +

+: + + + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookController.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookController.java index d00f114b8c..192f9c2342 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookController.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookController.java @@ -1,11 +1,19 @@ package com.baeldung.spring.cloud.bootstrap.svcbook.book; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - import java.util.List; import java.util.Map; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + @RestController @RequestMapping("/books") public class BookController { @@ -13,7 +21,7 @@ public class BookController { @Autowired private BookService bookService; - @GetMapping("") + @GetMapping public List findAllBooks() { return bookService.findAllBooks(); } @@ -23,7 +31,7 @@ public class BookController { return bookService.findBookById(bookId); } - @PostMapping("") + @PostMapping public Book createBook(@RequestBody Book book) { return bookService.createBook(book); } @@ -33,7 +41,12 @@ public class BookController { bookService.deleteBook(bookId); } - @PatchMapping("/{bookId") + @PutMapping("/{bookId}") + public Book updateBook(@RequestBody Book book, @PathVariable Long bookId) { + return bookService.updateBook(book, bookId); + } + + @PatchMapping("/{bookId}") public Book updateBook(@RequestBody Map updates, @PathVariable Long bookId) { return bookService.updateBook(updates, bookId); } diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java index cfcbf15757..106fdad5d9 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java @@ -1,13 +1,15 @@ package com.baeldung.spring.cloud.bootstrap.svcbook.book; +import java.util.List; +import java.util.Map; +import java.util.Optional; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import com.google.common.base.Preconditions; @Service @Transactional(readOnly = true) @@ -27,7 +29,7 @@ public class BookService { @Transactional(propagation = Propagation.REQUIRED) public Book createBook(Book book) { - Book newBook = new Book(); + final Book newBook = new Book(); newBook.setTitle(book.getTitle()); newBook.setAuthor(book.getAuthor()); return bookRepository.save(newBook); @@ -40,16 +42,25 @@ public class BookService { @Transactional(propagation = Propagation.REQUIRED) public Book updateBook(Map updates, Long bookId) { - Book book = findBookById(bookId); - updates.keySet().forEach(key -> { - switch (key) { - case "author": - book.setAuthor(updates.get(key)); - break; - case "title": - book.setTitle(updates.get(key)); - } - }); + final Book book = findBookById(bookId); + updates.keySet() + .forEach(key -> { + switch (key) { + case "author": + book.setAuthor(updates.get(key)); + break; + case "title": + book.setTitle(updates.get(key)); + } + }); + return bookRepository.save(book); + } + + @Transactional(propagation = Propagation.REQUIRED) + public Book updateBook(Book book, Long bookId) { + Preconditions.checkNotNull(book); + Preconditions.checkState(book.getId() == bookId); + Preconditions.checkNotNull(bookRepository.findOne(bookId)); return bookRepository.save(book); } } diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingController.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingController.java index 83452ad747..cbfeda49c0 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingController.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingController.java @@ -1,11 +1,20 @@ package com.baeldung.spring.cloud.bootstrap.svcrating.rating; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - import java.util.List; import java.util.Map; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + @RestController @RequestMapping("/ratings") public class RatingController { @@ -13,7 +22,7 @@ public class RatingController { @Autowired private RatingService ratingService; - @GetMapping("") + @GetMapping public List findRatingsByBookId(@RequestParam(required = false, defaultValue = "0") Long bookId) { if (bookId.equals(0L)) { return ratingService.findAllRatings(); @@ -21,7 +30,7 @@ public class RatingController { return ratingService.findRatingsByBookId(bookId); } - @PostMapping("") + @PostMapping public Rating createRating(@RequestBody Rating rating) { return ratingService.createRating(rating); } @@ -31,7 +40,12 @@ public class RatingController { ratingService.deleteRating(ratingId); } - @PatchMapping("/{ratingId") + @PutMapping("/{ratingId}") + public Rating updateRating(@RequestBody Rating rating, @PathVariable Long ratingId) { + return ratingService.updateRating(rating, ratingId); + } + + @PatchMapping("/{ratingId}") public Rating updateRating(@RequestBody Map updates, @PathVariable Long ratingId) { return ratingService.updateRating(updates, ratingId); } diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java index a2360b7be5..b05d7e2f1f 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java @@ -1,13 +1,15 @@ package com.baeldung.spring.cloud.bootstrap.svcrating.rating; +import java.util.List; +import java.util.Map; +import java.util.Optional; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import com.google.common.base.Preconditions; @Service @Transactional(readOnly = true) @@ -31,7 +33,7 @@ public class RatingService { @Transactional(propagation = Propagation.REQUIRED) public Rating createRating(Rating rating) { - Rating newRating = new Rating(); + final Rating newRating = new Rating(); newRating.setBookId(rating.getBookId()); newRating.setStars(rating.getStars()); return ratingRepository.save(newRating); @@ -44,14 +46,22 @@ public class RatingService { @Transactional(propagation = Propagation.REQUIRED) public Rating updateRating(Map updates, Long ratingId) { - Rating rating = findRatingById(ratingId); - updates.keySet().forEach(key -> { - switch (key) { + final Rating rating = findRatingById(ratingId); + updates.keySet() + .forEach(key -> { + switch (key) { case "stars": rating.setStars(Integer.parseInt(updates.get(key))); break; - } - }); + } + }); + return ratingRepository.save(rating); + } + + public Rating updateRating(Rating rating, Long ratingId) { + Preconditions.checkNotNull(rating); + Preconditions.checkState(rating.getId() == ratingId); + Preconditions.checkNotNull(ratingRepository.findOne(ratingId)); return ratingRepository.save(rating); } } diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/AnotherSampleDAOBean.java b/spring-core/src/main/java/com/baeldung/beaninjection/AnotherSampleDAOBean.java new file mode 100644 index 0000000000..6313ba5a65 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/AnotherSampleDAOBean.java @@ -0,0 +1,17 @@ +package com.baeldung.beaninjection; + +public class AnotherSampleDAOBean implements IAnotherSampleDAO { + + private String propertyY; + + public AnotherSampleDAOBean(String propertyY) { + this.propertyY = propertyY; + } + + // standard setters and getters + + public String getPropertyY() { + return propertyY; + } + +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/ExampleDAOBean.java b/spring-core/src/main/java/com/baeldung/beaninjection/ExampleDAOBean.java new file mode 100644 index 0000000000..cbc7b35a7c --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/ExampleDAOBean.java @@ -0,0 +1,39 @@ +package com.baeldung.beaninjection; + +import java.util.List; + +public class ExampleDAOBean implements IExampleDAO { + + private String propertyX; + + public ExampleDAOBean(String propertyX) { + this.propertyX = propertyX; + } + + public String getPropertyX() { + return propertyX; + } + + public void setPropertyX(String propertyX) { + this.propertyX = propertyX; + } + + @Override + public List getDomainList() { + // TODO Auto-generated method stub + return null; + } + + @Override + public SampleDomainObject createNewDomain(SampleDomainObject inputDomain) { + // TODO Auto-generated method stub + return null; + } + + @Override + public SampleDomainObject getSomeDomain() { + // TODO Auto-generated method stub + return new SampleDomainObject(); + } + +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/ExampleServiceBean.java b/spring-core/src/main/java/com/baeldung/beaninjection/ExampleServiceBean.java new file mode 100644 index 0000000000..e5a5dfff5d --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/ExampleServiceBean.java @@ -0,0 +1,47 @@ +package com.baeldung.beaninjection; + +import java.util.List; + +public class ExampleServiceBean implements IExampleService { + + private IExampleDAO exampleDAO; + private IAnotherSampleDAO anotherSampleDAO; + + public ExampleServiceBean(IExampleDAO exampleDAO) { + this.exampleDAO = exampleDAO; + } + + public void setAnotherSampleDAO(IAnotherSampleDAO anotherSampleDAO) { + this.anotherSampleDAO = anotherSampleDAO; + } + + // standard setters and getters + + public IAnotherSampleDAO getAnotherSampleDAO() { + return anotherSampleDAO; + } + + public void setExampleDAO(ExampleDAOBean exampleDAO) { + this.exampleDAO = exampleDAO; + } + + public IExampleDAO getExampleDAO() { + return exampleDAO; + } + + private String propertyX; + + public String getPropertyX() { + return propertyX; + } + + public void setPropertyX(String propertyX) { + this.propertyX = propertyX; + } + + public List serviceMethodX() { + /*get domain list from DAO .. business logic on domain objects..return*/ + return exampleDAO.getDomainList(); + } + +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/IAnotherSampleDAO.java b/spring-core/src/main/java/com/baeldung/beaninjection/IAnotherSampleDAO.java new file mode 100644 index 0000000000..ed4ad42705 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/IAnotherSampleDAO.java @@ -0,0 +1,5 @@ +package com.baeldung.beaninjection; + +public interface IAnotherSampleDAO { + +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/IExampleDAO.java b/spring-core/src/main/java/com/baeldung/beaninjection/IExampleDAO.java new file mode 100644 index 0000000000..f7dbd2f9fe --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/IExampleDAO.java @@ -0,0 +1,12 @@ +package com.baeldung.beaninjection; + +import java.util.List; + +public interface IExampleDAO { + + List getDomainList(); + + SampleDomainObject createNewDomain(SampleDomainObject domainObject); + + SampleDomainObject getSomeDomain(); +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/IExampleService.java b/spring-core/src/main/java/com/baeldung/beaninjection/IExampleService.java new file mode 100644 index 0000000000..9ea572d16b --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/IExampleService.java @@ -0,0 +1,9 @@ +package com.baeldung.beaninjection; + +import java.util.List; + +public interface IExampleService { + + List serviceMethodX(); + +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/SampleDomainObject.java b/spring-core/src/main/java/com/baeldung/beaninjection/SampleDomainObject.java new file mode 100644 index 0000000000..3a5a913aa6 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/SampleDomainObject.java @@ -0,0 +1,31 @@ +package com.baeldung.beaninjection; + +import java.io.Serializable; + +public class SampleDomainObject implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 449859763481296747L; + + private String domainPropX; + private String domainPropY; + + public String getDomainPropX() { + return domainPropX; + } + + public void setDomainPropX(String domainPropX) { + this.domainPropX = domainPropX; + } + + public String getDomainPropY() { + return domainPropY; + } + + public void setDomainPropY(String domainPropY) { + this.domainPropY = domainPropY; + } + +} diff --git a/spring-core/src/main/java/com/baeldung/configuration/ApplicationContextTestBeanInjectionTypes.java b/spring-core/src/main/java/com/baeldung/configuration/ApplicationContextTestBeanInjectionTypes.java new file mode 100644 index 0000000000..3939abf148 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/configuration/ApplicationContextTestBeanInjectionTypes.java @@ -0,0 +1,36 @@ +package com.baeldung.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import com.baeldung.beaninjection.AnotherSampleDAOBean; +import com.baeldung.beaninjection.ExampleDAOBean; +import com.baeldung.beaninjection.ExampleServiceBean; +import com.baeldung.beaninjection.IAnotherSampleDAO; +import com.baeldung.beaninjection.IExampleDAO; +import com.baeldung.beaninjection.IExampleService; + +@Configuration +@ComponentScan(basePackages = { "com.baeldung.beaninjection" }) +public class ApplicationContextTestBeanInjectionTypes { + + @Bean + public IExampleDAO exampleDAO() { + return new ExampleDAOBean("Mandatory DAO Property X"); + } + + @Bean + public IExampleService exampleServiceBean() { + ExampleServiceBean serviceBean = new ExampleServiceBean(exampleDAO()); + serviceBean.setAnotherSampleDAO(anotherSampleDAO()); + serviceBean.setPropertyX("Some Service Property X"); + return serviceBean; + } + + @Bean + public IAnotherSampleDAO anotherSampleDAO() { + return new AnotherSampleDAOBean("Mandatory DAO Property Y"); + } + +} diff --git a/spring-core/src/main/resources/beaninjectiontypes-context.xml b/spring-core/src/main/resources/beaninjectiontypes-context.xml new file mode 100644 index 0000000000..dfdea41cdc --- /dev/null +++ b/spring-core/src/main/resources/beaninjectiontypes-context.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionJavaConfigTest.java b/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionJavaConfigTest.java new file mode 100644 index 0000000000..4befd884eb --- /dev/null +++ b/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionJavaConfigTest.java @@ -0,0 +1,50 @@ +package com.baeldung.test.beaninjection; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.beaninjection.AnotherSampleDAOBean; +import com.baeldung.beaninjection.ExampleDAOBean; +import com.baeldung.beaninjection.ExampleServiceBean; +import com.baeldung.configuration.ApplicationContextTestBeanInjectionTypes; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = ApplicationContextTestBeanInjectionTypes.class) +public class BeanInjectionJavaConfigTest implements ApplicationContextAware { + + private ApplicationContext beanInjectedContext; + + @Test + public void testDAOInjectionByJava() { + ExampleServiceBean serviceBean = beanInjectedContext.getBean(ExampleServiceBean.class); + assertNotNull("Failed: Constructor Injection,Bean Reference Injection,Java Config, ExampleServiceBean", serviceBean.getExampleDAO()); + assertNotNull("Failed: Constructor Injection,Bean Reference Injection,Java Config, ExampleServiceBean", serviceBean.getAnotherSampleDAO()); + assertTrue("Failed: Constructor Injection,String Property , Java Config", serviceBean.getPropertyX() + .equals("Some Service Property X")); + } + + @Test + public void testPropertyInjectioninDAOByJava() { + ExampleDAOBean daoBean = beanInjectedContext.getBean(ExampleDAOBean.class); + assertTrue("Failed: Constructor Injection,String Property , Java Config", daoBean.getPropertyX() + .equals("Mandatory DAO Property X")); + + AnotherSampleDAOBean anotherDAOBean = beanInjectedContext.getBean(AnotherSampleDAOBean.class); + assertTrue("Failed: Constructor Injection,String Property , XML Config", anotherDAOBean.getPropertyY() + .equals("Mandatory DAO Property Y")); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + // TODO Auto-generated method stub + this.beanInjectedContext = applicationContext; + } +} diff --git a/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionXMLConfigTest.java b/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionXMLConfigTest.java new file mode 100644 index 0000000000..d19a099aad --- /dev/null +++ b/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionXMLConfigTest.java @@ -0,0 +1,49 @@ +package com.baeldung.test.beaninjection; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.beaninjection.AnotherSampleDAOBean; +import com.baeldung.beaninjection.ExampleDAOBean; +import com.baeldung.beaninjection.ExampleServiceBean; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "classpath:beaninjectiontypes-context.xml") +public class BeanInjectionXMLConfigTest implements ApplicationContextAware { + + private ApplicationContext beanInjectedContext; + + @Test + public void testDAOInjectionByXML() { + ExampleServiceBean serviceBean = beanInjectedContext.getBean(ExampleServiceBean.class); + assertNotNull("Failed: Constructor Injection,Bean Reference Injection,XML Config, ExampleServiceBean", serviceBean.getExampleDAO()); + assertNotNull("Failed: Constructor Injection,Bean Reference Injection,XML Config, ExampleServiceBean", serviceBean.getAnotherSampleDAO()); + assertTrue("Failed: Constructor Injection,String Property , XML Config", serviceBean.getPropertyX() + .equals("Some Service Property X")); + } + + @Test + public void testPropertyInjectioninDAOByXML() { + ExampleDAOBean daoBean = beanInjectedContext.getBean(ExampleDAOBean.class); + assertTrue("Failed: Constructor Injection,String Property , XML Config", daoBean.getPropertyX() + .equals("Mandatory DAO Property X")); + + AnotherSampleDAOBean anotherDAOBean = beanInjectedContext.getBean(AnotherSampleDAOBean.class); + assertTrue("Failed: Constructor Injection,String Property , XML Config", anotherDAOBean.getPropertyY() + .equals("Mandatory DAO Property Y")); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + // TODO Auto-generated method stub + this.beanInjectedContext = applicationContext; + } +} diff --git a/spring-kafka/README.md b/spring-kafka/README.md new file mode 100644 index 0000000000..2731eca042 --- /dev/null +++ b/spring-kafka/README.md @@ -0,0 +1,9 @@ +# Spring Kakfa + +This is a simple Spring Boot app to demonstrate sending and receiving of messages in Kafka using spring-kafka. + +As Kafka topics are not created automatically by default, this application requires that a topic named 'baeldung' is created manually. + +`$ bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic baeldung` + +Two listeners with group Ids **foo** and **bar** are configured. When run successfully, the *Hello World!* message will be received by both the listeners and logged on console. diff --git a/spring-kafka/pom.xml b/spring-kafka/pom.xml new file mode 100644 index 0000000000..73eaf3acff --- /dev/null +++ b/spring-kafka/pom.xml @@ -0,0 +1,46 @@ + + 4.0.0 + + com.baeldung + spring-kafka + 0.0.1-SNAPSHOT + + spring-kafka + Intro to Kafka with Spring + + + 1.8 + 1.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-parent + 1.5.2.RELEASE + + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.kafka + spring-kafka + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java new file mode 100644 index 0000000000..252054a9f1 --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java @@ -0,0 +1,72 @@ +package com.baeldung.spring.kafka; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.core.KafkaTemplate; + +@SpringBootApplication +public class KafkaApplication { + + public static void main(String[] args) throws Exception { + ConfigurableApplicationContext context = SpringApplication.run(KafkaApplication.class, args); + MessageProducer producer = context.getBean(MessageProducer.class); + producer.sendMessage("Hello, World!"); + + MessageListener listener = context.getBean(MessageListener.class); + listener.latch.await(20, TimeUnit.SECONDS); + Thread.sleep(60000); + context.close(); + + } + + @Bean + public MessageProducer messageProducer() { + return new MessageProducer(); + } + + @Bean + public MessageListener messageListener() { + return new MessageListener(); + } + + public static class MessageProducer { + + @Autowired + private KafkaTemplate kafkaTemplate; + + @Value(value = "${message.topic.name}") + private String topicName; + + public void sendMessage(String message) { + kafkaTemplate.send(topicName, message); + } + + } + + public static class MessageListener { + + private CountDownLatch latch = new CountDownLatch(2); + + @KafkaListener(topics = "${message.topic.name}", group = "foo", containerFactory = "fooKafkaListenerContainerFactory") + public void listenGroupFoo(String message) { + System.out.println("Received Messasge in group 'foo': " + message); + latch.countDown(); + } + + @KafkaListener(topics = "${message.topic.name}", group = "bar", containerFactory = "barKafkaListenerContainerFactory") + public void listenGroupBar(String message) { + System.out.println("Received Messasge in group 'bar': " + message); + latch.countDown(); + } + + } + +} diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java new file mode 100644 index 0000000000..f9edda2435 --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java @@ -0,0 +1,45 @@ +package com.baeldung.spring.kafka; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; + +@EnableKafka +@Configuration +public class KafkaConsumerConfig { + + @Value(value = "${kafka.bootstrapAddress}") + private String bootstrapAddress; + + public ConsumerFactory consumerFactory(String groupId) { + Map props = new HashMap<>(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); + props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + return new DefaultKafkaConsumerFactory<>(props); + } + + @Bean + public ConcurrentKafkaListenerContainerFactory fooKafkaListenerContainerFactory() { + ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); + factory.setConsumerFactory(consumerFactory("foo")); + return factory; + } + + @Bean + public ConcurrentKafkaListenerContainerFactory barKafkaListenerContainerFactory() { + ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); + factory.setConsumerFactory(consumerFactory("bar")); + return factory; + } +} diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java new file mode 100644 index 0000000000..4f9f9719ee --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java @@ -0,0 +1,36 @@ +package com.baeldung.spring.kafka; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.serialization.StringSerializer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.core.ProducerFactory; + +@Configuration +public class KafkaProducerConfig { + + @Value(value = "${kafka.bootstrapAddress}") + private String bootstrapAddress; + + @Bean + public ProducerFactory producerFactory() { + Map configProps = new HashMap(); + configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); + configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + return new DefaultKafkaProducerFactory(configProps); + } + + @Bean + public KafkaTemplate kafkaTemplate() { + KafkaTemplate template = + new KafkaTemplate(producerFactory()); + return template; + } +} diff --git a/spring-kafka/src/main/resources/application.properties b/spring-kafka/src/main/resources/application.properties new file mode 100644 index 0000000000..a1d73b204c --- /dev/null +++ b/spring-kafka/src/main/resources/application.properties @@ -0,0 +1,2 @@ +kafka.bootstrapAddress=localhost:9092 +message.topic.name=baeldung diff --git a/spring-security-mvc-boot/README.MD b/spring-security-mvc-boot/README.MD index 3e789dedad..70b0f23cbb 100644 --- a/spring-security-mvc-boot/README.MD +++ b/spring-security-mvc-boot/README.MD @@ -6,3 +6,4 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com - [Custom AccessDecisionVoters in Spring Security](http://www.baeldung.com/spring-security-custom-voter) - [Spring Security: Authentication with a Database-backed UserDetailsService](http://www.baeldung.com/spring-security-authentication-with-a-database) - [Two Login Pages with Spring Security](http://www.baeldung.com/spring-security-two-login-pages) +- [Multiple Entry Points in Spring Security](http://www.baeldung.com/spring-security-multiple-entry-points) diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/MultipleEntryPointsSecurityConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/MultipleEntryPointsSecurityConfig.java index 9da2ef20e3..9f2eba0a2e 100644 --- a/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/MultipleEntryPointsSecurityConfig.java +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/MultipleEntryPointsSecurityConfig.java @@ -9,6 +9,10 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; +import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @Configuration @EnableWebSecurity @@ -26,51 +30,60 @@ public class MultipleEntryPointsSecurityConfig { @Order(1) public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter { - public App1ConfigurationAdapter() { - super(); - } - @Override protected void configure(HttpSecurity http) throws Exception { //@formatter:off http.antMatcher("/admin/**") .authorizeRequests().anyRequest().hasRole("ADMIN") - .and().httpBasic() + .and().httpBasic().authenticationEntryPoint(authenticationEntryPoint()) .and().exceptionHandling().accessDeniedPage("/403"); //@formatter:on } + + @Bean + public AuthenticationEntryPoint authenticationEntryPoint(){ + BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint(); + entryPoint.setRealmName("admin realm"); + return entryPoint; + } } @Configuration @Order(2) public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter { - public App2ConfigurationAdapter() { - super(); - } - protected void configure(HttpSecurity http) throws Exception { + //@formatter:off http.antMatcher("/user/**") .authorizeRequests().anyRequest().hasRole("USER") - .and().formLogin().loginPage("/userLogin").loginProcessingUrl("/user/login") + .and().formLogin().loginProcessingUrl("/user/login") .failureUrl("/userLogin?error=loginError").defaultSuccessUrl("/user/myUserPage") .and().logout().logoutUrl("/user/logout").logoutSuccessUrl("/multipleHttpLinks") .deleteCookies("JSESSIONID") - .and().exceptionHandling().accessDeniedPage("/403") + .and().exceptionHandling() + .defaultAuthenticationEntryPointFor(loginUrlauthenticationEntryPointWithWarning(), new AntPathRequestMatcher("/user/private/**")) + .defaultAuthenticationEntryPointFor(loginUrlauthenticationEntryPoint(), new AntPathRequestMatcher("/user/general/**")) + .accessDeniedPage("/403") .and().csrf().disable(); //@formatter:on } + + @Bean + public AuthenticationEntryPoint loginUrlauthenticationEntryPoint(){ + return new LoginUrlAuthenticationEntryPoint("/userLogin"); + } + + @Bean + public AuthenticationEntryPoint loginUrlauthenticationEntryPointWithWarning(){ + return new LoginUrlAuthenticationEntryPoint("/userLoginWithWarning"); + } } @Configuration @Order(3) public static class App3ConfigurationAdapter extends WebSecurityConfigurerAdapter { - public App3ConfigurationAdapter() { - super(); - } - protected void configure(HttpSecurity http) throws Exception { http.antMatcher("/guest/**").authorizeRequests().anyRequest().permitAll(); } diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/PagesController.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/PagesController.java index 3b59678b87..b3462d4061 100644 --- a/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/PagesController.java +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/PagesController.java @@ -16,10 +16,15 @@ public class PagesController { return "multipleHttpElems/myAdminPage"; } - @RequestMapping("/user/myUserPage") + @RequestMapping("/user/general/myUserPage") public String getUserPage() { return "multipleHttpElems/myUserPage"; } + + @RequestMapping("/user/private/myPrivateUserPage") + public String getPrivateUserPage() { + return "multipleHttpElems/myPrivateUserPage"; + } @RequestMapping("/guest/myGuestPage") public String getGuestPage() { @@ -30,6 +35,11 @@ public class PagesController { public String getUserLoginPage() { return "multipleHttpElems/login"; } + + @RequestMapping("/userLoginWithWarning") + public String getUserLoginPageWithWarning() { + return "multipleHttpElems/loginWithWarning"; + } @RequestMapping("/403") public String getAccessDeniedPage() { diff --git a/spring-security-mvc-boot/src/main/resources/spring-security-multiple-entry.xml b/spring-security-mvc-boot/src/main/resources/spring-security-multiple-entry.xml index 1a68bd5c30..c026700810 100644 --- a/spring-security-mvc-boot/src/main/resources/spring-security-multiple-entry.xml +++ b/spring-security-mvc-boot/src/main/resources/spring-security-multiple-entry.xml @@ -2,7 +2,7 @@ @@ -14,9 +14,10 @@ - - - + + @@ -24,14 +25,41 @@ + + + + + + + + + + + + + + + + - + + + + + + diff --git a/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/loginWithWarning.html b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/loginWithWarning.html new file mode 100644 index 0000000000..a5b2eaf3dc --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/loginWithWarning.html @@ -0,0 +1,28 @@ + + + + +

Login

+

Warning! You are about to access sensible data!

+ +
+ + + + + + + + + + + + + + +
Username:
Password:
+ +
+ + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/multipleHttpLinks.html b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/multipleHttpLinks.html index 4a2af1d649..676badb16f 100644 --- a/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/multipleHttpLinks.html +++ b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/multipleHttpLinks.html @@ -8,7 +8,9 @@ Admin page
-User page +User page +
+Private user page
Guest page diff --git a/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myPrivateUserPage.html b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myPrivateUserPage.html new file mode 100644 index 0000000000..52045ec320 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myPrivateUserPage.html @@ -0,0 +1,13 @@ + + + + +Insert title here + + +Welcome user to your private page! Logout + +

+Back to links + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/test/java/org/baeldung/web/MultipleEntryPointsTest.java b/spring-security-mvc-boot/src/test/java/org/baeldung/web/MultipleEntryPointsTest.java index 96d38d4943..050d2363af 100644 --- a/spring-security-mvc-boot/src/test/java/org/baeldung/web/MultipleEntryPointsTest.java +++ b/spring-security-mvc-boot/src/test/java/org/baeldung/web/MultipleEntryPointsTest.java @@ -46,9 +46,9 @@ public class MultipleEntryPointsTest { @Test public void whenTestUserCredentials_thenOk() throws Exception { - mockMvc.perform(get("/user/myUserPage")).andExpect(status().isFound()); + mockMvc.perform(get("/user/general/myUserPage")).andExpect(status().isFound()); - mockMvc.perform(get("/user/myUserPage").with(user("user").password("userPass").roles("USER"))).andExpect(status().isOk()); + mockMvc.perform(get("/user/general/myUserPage").with(user("user").password("userPass").roles("USER"))).andExpect(status().isOk()); mockMvc.perform(get("/admin/myAdminPage").with(user("user").password("userPass").roles("USER"))).andExpect(status().isForbidden()); } diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/IEnhancedSpecification.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/IEnhancedSpecification.java new file mode 100644 index 0000000000..58d08a161e --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/IEnhancedSpecification.java @@ -0,0 +1,10 @@ +package org.baeldung.persistence; + +import org.springframework.data.jpa.domain.Specification; + +public interface IEnhancedSpecification extends Specification { + + default boolean isOfLowPrecedence() { + return false; + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/GenericSpecificationsBuilder.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/GenericSpecificationsBuilder.java new file mode 100644 index 0000000000..4936c2e1c1 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/GenericSpecificationsBuilder.java @@ -0,0 +1,64 @@ +package org.baeldung.persistence.dao; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.baeldung.web.util.SearchOperation; +import org.baeldung.web.util.SpecSearchCriteria; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.domain.Specifications; + +public class GenericSpecificationsBuilder { + + private final List params; + + public GenericSpecificationsBuilder() { + this.params = new ArrayList<>(); + } + + public final GenericSpecificationsBuilder with(final String key, final String operation, final Object value, + final String prefix, final String suffix) { + return with(null, key, operation, value, prefix, suffix); + } + + public final GenericSpecificationsBuilder with(final String precedenceIndicator, final String key, + final String operation, final Object value, final String prefix, final String suffix) { + SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); + if (op != null) { + if (op == SearchOperation.EQUALITY) // the operation may be complex operation + { + final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + + if (startWithAsterisk && endWithAsterisk) { + op = SearchOperation.CONTAINS; + } else if (startWithAsterisk) { + op = SearchOperation.ENDS_WITH; + } else if (endWithAsterisk) { + op = SearchOperation.STARTS_WITH; + } + } + params.add(new SpecSearchCriteria(precedenceIndicator, key, op, value)); + } + return this; + } + + public Specification build(Function> converter) { + + if (params.size() == 0) + return null; + + params.sort((spec0, spec1) -> Boolean.compare(spec0.isLowPrecedence(), spec1.isLowPrecedence())); + + final List> specs = params.stream().map(converter).collect(Collectors.toCollection(ArrayList::new)); + + Specification result = specs.get(0); + + for (int idx = 1; idx < specs.size(); idx++) { + result=params.get(idx).isLowPrecedence()? Specifications.where(result).or(specs.get(idx)): Specifications.where(result).and(specs.get(idx)); + } + return result; + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java index e41c7ca663..2788c46fde 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java @@ -11,39 +11,39 @@ import org.springframework.data.jpa.domain.Specification; public class UserSpecification implements Specification { - private SpecSearchCriteria criteria; + private SpecSearchCriteria criteria; - public UserSpecification(final SpecSearchCriteria criteria) { - super(); - this.criteria = criteria; - } + public UserSpecification(final SpecSearchCriteria criteria) { + super(); + this.criteria = criteria; + } - public SpecSearchCriteria getCriteria() { - return criteria; - } + public SpecSearchCriteria getCriteria() { + return criteria; + } - @Override - public Predicate toPredicate(final Root root, final CriteriaQuery query, final CriteriaBuilder builder) { - switch (criteria.getOperation()) { - case EQUALITY: - return builder.equal(root.get(criteria.getKey()), criteria.getValue()); - case NEGATION: - return builder.notEqual(root.get(criteria.getKey()), criteria.getValue()); - case GREATER_THAN: - return builder.greaterThan(root. get(criteria.getKey()), criteria.getValue().toString()); - case LESS_THAN: - return builder.lessThan(root. get(criteria.getKey()), criteria.getValue().toString()); - case LIKE: - return builder.like(root. get(criteria.getKey()), criteria.getValue().toString()); - case STARTS_WITH: - return builder.like(root. get(criteria.getKey()), criteria.getValue() + "%"); - case ENDS_WITH: - return builder.like(root. get(criteria.getKey()), "%" + criteria.getValue()); - case CONTAINS: - return builder.like(root. get(criteria.getKey()), "%" + criteria.getValue() + "%"); - default: - return null; - } - } + @Override + public Predicate toPredicate(final Root root, final CriteriaQuery query, final CriteriaBuilder builder) { + switch (criteria.getOperation()) { + case EQUALITY: + return builder.equal(root.get(criteria.getKey()), criteria.getValue()); + case NEGATION: + return builder.notEqual(root.get(criteria.getKey()), criteria.getValue()); + case GREATER_THAN: + return builder.greaterThan(root. get(criteria.getKey()), criteria.getValue().toString()); + case LESS_THAN: + return builder.lessThan(root. get(criteria.getKey()), criteria.getValue().toString()); + case LIKE: + return builder.like(root. get(criteria.getKey()), criteria.getValue().toString()); + case STARTS_WITH: + return builder.like(root. get(criteria.getKey()), criteria.getValue() + "%"); + case ENDS_WITH: + return builder.like(root. get(criteria.getKey()), "%" + criteria.getValue()); + case CONTAINS: + return builder.like(root. get(criteria.getKey()), "%" + criteria.getValue() + "%"); + default: + return null; + } + } } diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java index 3db4267ae0..8a10163f51 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java @@ -1,60 +1,74 @@ -package org.baeldung.persistence.dao; - -import java.util.ArrayList; -import java.util.List; - -import org.baeldung.persistence.model.User; -import org.baeldung.web.util.SearchOperation; -import org.baeldung.web.util.SpecSearchCriteria; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.domain.Specifications; - -public final class UserSpecificationsBuilder { - - private final List params; - - public UserSpecificationsBuilder() { - params = new ArrayList(); - } - - // API - - public final UserSpecificationsBuilder with(final String key, final String operation, final Object value, final String prefix, final String suffix) { - SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); - if (op != null) { - if (op == SearchOperation.EQUALITY) // the operation may be complex operation - { - final boolean startWithAsterisk = prefix.contains("*"); - final boolean endWithAsterisk = suffix.contains("*"); - - if (startWithAsterisk && endWithAsterisk) { - op = SearchOperation.CONTAINS; - } else if (startWithAsterisk) { - op = SearchOperation.ENDS_WITH; - } else if (endWithAsterisk) { - op = SearchOperation.STARTS_WITH; - } - } - params.add(new SpecSearchCriteria(key, op, value)); - } - return this; - } - - public Specification build() { - if (params.size() == 0) { - return null; - } - - final List> specs = new ArrayList>(); - for (final SpecSearchCriteria param : params) { - specs.add(new UserSpecification(param)); - } - - Specification result = specs.get(0); - for (int i = 1; i < specs.size(); i++) { - result = Specifications.where(result).and(specs.get(i)); - } - return result; - } - -} +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.User; +import org.baeldung.web.util.SearchOperation; +import org.baeldung.web.util.SpecSearchCriteria; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.domain.Specifications; + +import java.util.ArrayList; +import java.util.List; + +public final class UserSpecificationsBuilder { + + private final List params; + + public UserSpecificationsBuilder() { + params = new ArrayList(); + } + + // API + + public final UserSpecificationsBuilder with(final String key, final String operation, final Object value, final String prefix, final String suffix) { + return with(null, key, operation, value, prefix, suffix); + } + + public final UserSpecificationsBuilder with(final String precedenceIndicator, final String key, final String operation, final Object value, final String prefix, final String suffix) { + SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); + if (op != null) { + if (op == SearchOperation.EQUALITY) { // the operation may be complex operation + final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + + if (startWithAsterisk && endWithAsterisk) { + op = SearchOperation.CONTAINS; + } else if (startWithAsterisk) { + op = SearchOperation.ENDS_WITH; + } else if (endWithAsterisk) { + op = SearchOperation.STARTS_WITH; + } + } + params.add(new SpecSearchCriteria(precedenceIndicator, key, op, value)); + } + return this; + } + + public Specification build() { + + if (params.size() == 0) + return null; + + params.sort((spec0, spec1) -> { + return Boolean.compare(spec0.isLowPrecedence(), spec1.isLowPrecedence()); + }); + + Specification result = new UserSpecification(params.get(0)); + + for (int i = 1; i < params.size(); i++) { + result = params.get(i).isLowPrecedence() ? Specifications.where(result).or(new UserSpecification(params.get(i))) : Specifications.where(result).and(new UserSpecification(params.get(i))); + + } + + return result; + } + + public final UserSpecificationsBuilder with(UserSpecification spec) { + params.add(spec.getCriteria()); + return this; + } + + public final UserSpecificationsBuilder with(SpecSearchCriteria criteria) { + params.add(criteria); + return this; + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java index d20423ddc0..fff089a62b 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java @@ -1,15 +1,12 @@ package org.baeldung.web.controller; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.baeldung.persistence.dao.IUserDAO; -import org.baeldung.persistence.dao.MyUserPredicatesBuilder; -import org.baeldung.persistence.dao.MyUserRepository; -import org.baeldung.persistence.dao.UserRepository; -import org.baeldung.persistence.dao.UserSpecificationsBuilder; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.querydsl.core.types.Predicate; +import com.querydsl.core.types.dsl.BooleanExpression; +import cz.jirutka.rsql.parser.RSQLParser; +import cz.jirutka.rsql.parser.ast.Node; +import org.baeldung.persistence.dao.*; import org.baeldung.persistence.dao.rsql.CustomRsqlVisitor; import org.baeldung.persistence.model.MyUser; import org.baeldung.persistence.model.User; @@ -20,20 +17,12 @@ import org.springframework.data.jpa.domain.Specification; import org.springframework.data.querydsl.binding.QuerydslPredicate; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.*; -import com.google.common.base.Joiner; -import com.google.common.base.Preconditions; -import com.querydsl.core.types.Predicate; -import com.querydsl.core.types.dsl.BooleanExpression; - -import cz.jirutka.rsql.parser.RSQLParser; -import cz.jirutka.rsql.parser.ast.Node; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; //@EnableSpringDataWebSupport @Controller @@ -84,6 +73,25 @@ public class UserController { return dao.findAll(spec); } + @RequestMapping(method = RequestMethod.GET, value = "/users/espec") + @ResponseBody + public List findAllByOptionalSpecification(@RequestParam(value = "search") final String search) { + final Specification spec = resolveSpecification(search); + return dao.findAll(spec); + } + + protected Specification resolveSpecification(String searchParameters) { + + final UserSpecificationsBuilder builder = new UserSpecificationsBuilder(); + final String operationSetExper = Joiner.on("|").join(SearchOperation.SIMPLE_OPERATION_SET); + final Pattern pattern = Pattern.compile("(\\p{Punct}?)(\\w+?)(" + operationSetExper + ")(\\p{Punct}?)(\\w+?)(\\p{Punct}?),"); + final Matcher matcher = pattern.matcher(searchParameters + ","); + while (matcher.find()) { + builder.with(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(5), matcher.group(4), matcher.group(6)); + } + return builder.build(); + } + @RequestMapping(method = RequestMethod.GET, value = "/myusers") @ResponseBody public Iterable findAllByQuerydsl(@RequestParam(value = "search") final String search) { diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java index 703f9b93f6..41a556c18a 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java @@ -1,24 +1,28 @@ -package org.baeldung.web.util; - -public enum SearchOperation { - EQUALITY, NEGATION, GREATER_THAN, LESS_THAN, LIKE, STARTS_WITH, ENDS_WITH, CONTAINS; - - public static final String[] SIMPLE_OPERATION_SET = { ":", "!", ">", "<", "~" }; - - public static SearchOperation getSimpleOperation(final char input) { - switch (input) { - case ':': - return EQUALITY; - case '!': - return NEGATION; - case '>': - return GREATER_THAN; - case '<': - return LESS_THAN; - case '~': - return LIKE; - default: - return null; - } - } -} +package org.baeldung.web.util; + +public enum SearchOperation { + EQUALITY, NEGATION, GREATER_THAN, LESS_THAN, LIKE, STARTS_WITH, ENDS_WITH, CONTAINS; + + public static final String[] SIMPLE_OPERATION_SET = { ":", "!", ">", "<", "~" }; + + public static final String LOW_PRECEDENCE_INDICATOR="'"; + + public static final String ZERO_OR_MORE_REGEX="*"; + + public static SearchOperation getSimpleOperation(final char input) { + switch (input) { + case ':': + return EQUALITY; + case '!': + return NEGATION; + case '>': + return GREATER_THAN; + case '<': + return LESS_THAN; + case '~': + return LIKE; + default: + return null; + } + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java index 4a04d395fa..7dbb66edea 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java @@ -1,44 +1,61 @@ -package org.baeldung.web.util; - -public class SpecSearchCriteria { - - private String key; - private SearchOperation operation; - private Object value; - - public SpecSearchCriteria() { - - } - - public SpecSearchCriteria(final String key, final SearchOperation operation, final Object value) { - super(); - this.key = key; - this.operation = operation; - this.value = value; - } - - public String getKey() { - return key; - } - - public void setKey(final String key) { - this.key = key; - } - - public SearchOperation getOperation() { - return operation; - } - - public void setOperation(final SearchOperation operation) { - this.operation = operation; - } - - public Object getValue() { - return value; - } - - public void setValue(final Object value) { - this.value = value; - } - -} +package org.baeldung.web.util; + +public class SpecSearchCriteria { + + private String key; + private SearchOperation operation; + private Object value; + private boolean lowPrecedence; + + public SpecSearchCriteria() { + + } + + public SpecSearchCriteria(final String key, final SearchOperation operation, final Object value) { + super(); + this.key = key; + this.operation = operation; + this.value = value; + } + + public SpecSearchCriteria(final String lowPrecedenceIndicator, final String key, final SearchOperation operation, final Object value) { + super(); + this.lowPrecedence = lowPrecedenceIndicator != null && lowPrecedenceIndicator.equals(SearchOperation.LOW_PRECEDENCE_INDICATOR); + this.key = key; + this.operation = operation; + this.value = value; + } + + public String getKey() { + return key; + } + + public void setKey(final String key) { + this.key = key; + } + + public SearchOperation getOperation() { + return operation; + } + + public void setOperation(final SearchOperation operation) { + this.operation = operation; + } + + public Object getValue() { + return value; + } + + public void setValue(final Object value) { + this.value = value; + } + + public boolean isLowPrecedence() { + return lowPrecedence; + } + + public void setLowPrecedence(boolean lowPrecedence) { + this.lowPrecedence = lowPrecedence; + } + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationIntegrationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationIntegrationTest.java index 8bd4857e85..e5c408bfdb 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationIntegrationTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationIntegrationTest.java @@ -1,119 +1,160 @@ -package org.baeldung.persistence.query; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.collection.IsIn.isIn; -import static org.hamcrest.core.IsNot.not; - -import java.util.List; - -import org.baeldung.persistence.dao.UserRepository; -import org.baeldung.persistence.dao.UserSpecification; -import org.baeldung.persistence.model.User; -import org.baeldung.spring.PersistenceConfig; -import org.baeldung.web.util.SearchOperation; -import org.baeldung.web.util.SpecSearchCriteria; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.jpa.domain.Specifications; -import org.springframework.test.annotation.Rollback; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.transaction.annotation.Transactional; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { PersistenceConfig.class }) -@Transactional -@Rollback -public class JPASpecificationIntegrationTest { - - @Autowired - private UserRepository repository; - - private User userJohn; - - private User userTom; - - @Before - public void init() { - userJohn = new User(); - userJohn.setFirstName("john"); - userJohn.setLastName("doe"); - userJohn.setEmail("john@doe.com"); - userJohn.setAge(22); - repository.save(userJohn); - - userTom = new User(); - userTom.setFirstName("tom"); - userTom.setLastName("doe"); - userTom.setEmail("tom@doe.com"); - userTom.setAge(26); - repository.save(userTom); - } - - @Test - public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.EQUALITY, "john")); - final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("lastName", SearchOperation.EQUALITY, "doe")); - final List results = repository.findAll(Specifications.where(spec).and(spec1)); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.NEGATION, "john")); - final List results = repository.findAll(Specifications.where(spec)); - - assertThat(userTom, isIn(results)); - assertThat(userJohn, not(isIn(results))); - } - - @Test - public void givenMinAge_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "25")); - final List results = repository.findAll(Specifications.where(spec)); - - assertThat(userTom, isIn(results)); - assertThat(userJohn, not(isIn(results))); - } - - @Test - public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.STARTS_WITH, "jo")); - final List results = repository.findAll(spec); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.ENDS_WITH, "n")); - final List results = repository.findAll(spec); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.CONTAINS, "oh")); - final List results = repository.findAll(spec); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "20")); - final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.LESS_THAN, "25")); - final List results = repository.findAll(Specifications.where(spec).and(spec1)); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } -} +package org.baeldung.persistence.query; + +import org.baeldung.persistence.dao.GenericSpecificationsBuilder; +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.dao.UserSpecification; +import org.baeldung.persistence.dao.UserSpecificationsBuilder; +import org.baeldung.persistence.model.User; +import org.baeldung.spring.PersistenceConfig; +import org.baeldung.web.util.SearchOperation; +import org.baeldung.web.util.SpecSearchCriteria; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.domain.Specifications; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.function.Function; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.hamcrest.collection.IsIn.isIn; +import static org.hamcrest.core.IsNot.not; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }) +@Transactional +@Rollback +public class JPASpecificationIntegrationTest { + + @Autowired + private UserRepository repository; + + private User userJohn; + + private User userTom; + + private User userPercy; + + @Before + public void init() { + userJohn = new User(); + userJohn.setFirstName("john"); + userJohn.setLastName("doe"); + userJohn.setEmail("john@doe.com"); + userJohn.setAge(22); + repository.save(userJohn); + + userTom = new User(); + userTom.setFirstName("tom"); + userTom.setLastName("doe"); + userTom.setEmail("tom@doe.com"); + userTom.setAge(26); + repository.save(userTom); + + userPercy = new User(); + userPercy.setFirstName("percy"); + userPercy.setLastName("blackney"); + userPercy.setEmail("percy@blackney.com"); + userPercy.setAge(30); + repository.save(userPercy); + } + + @Test + public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.EQUALITY, "john")); + final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("lastName", SearchOperation.EQUALITY, "doe")); + final List results = repository.findAll(Specifications.where(spec).and(spec1)); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect() { + UserSpecificationsBuilder builder = new UserSpecificationsBuilder(); + + final SpecSearchCriteria spec = new SpecSearchCriteria("'", "firstName", SearchOperation.EQUALITY, "john"); + final SpecSearchCriteria spec1 = new SpecSearchCriteria("lastName", SearchOperation.EQUALITY, "doe"); + + final List results = repository.findAll(builder.with(spec1).with(spec).build()); + + assertThat(results, hasSize(2)); + assertThat(userJohn, isIn(results)); + assertThat(userTom, isIn(results)); + } + + @Test + public void givenFirstOrLastNameGenericBuilder_whenGettingListOfUsers_thenCorrect() { + GenericSpecificationsBuilder builder = new GenericSpecificationsBuilder(); + Function> converter = UserSpecification::new; + builder.with("'", "firstName", ":", "john", null, null); + builder.with(null, "lastName", ":", "doe", null, null); + + final List results = repository.findAll(builder.build(converter)); + assertThat(results, hasSize(2)); + assertThat(userJohn, isIn(results)); + assertThat(userTom, isIn(results)); + } + + @Test + public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.NEGATION, "john")); + final List results = repository.findAll(Specifications.where(spec)); + + assertThat(userTom, isIn(results)); + assertThat(userJohn, not(isIn(results))); + } + + @Test + public void givenMinAge_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "25")); + final List results = repository.findAll(Specifications.where(spec)); + + assertThat(userTom, isIn(results)); + assertThat(userJohn, not(isIn(results))); + } + + @Test + public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.STARTS_WITH, "jo")); + final List results = repository.findAll(spec); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.ENDS_WITH, "n")); + final List results = repository.findAll(spec); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.CONTAINS, "oh")); + final List results = repository.findAll(spec); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "20")); + final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.LESS_THAN, "25")); + final List results = repository.findAll(Specifications.where(spec).and(spec1)); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationLiveTest.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationLiveTest.java index 3b85cfb487..55fde80add 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationLiveTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationLiveTest.java @@ -1,112 +1,122 @@ -package org.baeldung.persistence.query; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.baeldung.persistence.model.User; -import org.junit.Before; -import org.junit.Test; -import org.springframework.test.context.ActiveProfiles; - -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.response.Response; -import com.jayway.restassured.specification.RequestSpecification; - -//@RunWith(SpringJUnit4ClassRunner.class) -//@ContextConfiguration(classes = { ConfigTest.class, PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) -@ActiveProfiles("test") -public class JPASpecificationLiveTest { - - // @Autowired - // private UserRepository repository; - - private User userJohn; - - private User userTom; - - private final String URL_PREFIX = "http://localhost:8082/spring-security-rest-full/auth/users/spec?search="; - - @Before - public void init() { - userJohn = new User(); - userJohn.setFirstName("john"); - userJohn.setLastName("doe"); - userJohn.setEmail("john@doe.com"); - userJohn.setAge(22); - // repository.save(userJohn); - - userTom = new User(); - userTom.setFirstName("tom"); - userTom.setLastName("doe"); - userTom.setEmail("tom@doe.com"); - userTom.setAge(26); - // repository.save(userTom); - } - - @Test - public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "firstName:john,lastName:doe"); - final String result = response.body().asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "firstName!john"); - final String result = response.body().asString(); - - assertTrue(result.contains(userTom.getEmail())); - assertFalse(result.contains(userJohn.getEmail())); - } - - @Test - public void givenMinAge_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "age>25"); - final String result = response.body().asString(); - - assertTrue(result.contains(userTom.getEmail())); - assertFalse(result.contains(userJohn.getEmail())); - } - - @Test - public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "firstName:jo*"); - final String result = response.body().asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "firstName:*n"); - final String result = response.body().asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "firstName:*oh*"); - final String result = response.body().asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "age>20,age<25"); - final String result = response.body().asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - private final RequestSpecification givenAuth() { - return RestAssured.given().auth().preemptive().basic("user1", "user1Pass"); - } -} +package org.baeldung.persistence.query; + +import com.jayway.restassured.RestAssured; +import com.jayway.restassured.response.Response; +import com.jayway.restassured.specification.RequestSpecification; +import org.baeldung.persistence.model.User; +import org.junit.Before; +import org.junit.Test; +import org.springframework.test.context.ActiveProfiles; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +//@RunWith(SpringJUnit4ClassRunner.class) +//@ContextConfiguration(classes = { ConfigTest.class, +// PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +@ActiveProfiles("test") +public class JPASpecificationLiveTest { + + // @Autowired + // private UserRepository repository; + + private User userJohn; + + private User userTom; + + private final String URL_PREFIX = "http://localhost:8082/spring-security-rest-full/auth/users/spec?search="; + + @Before + public void init() { + userJohn = new User(); + userJohn.setFirstName("john"); + userJohn.setLastName("doe"); + userJohn.setEmail("john@doe.com"); + userJohn.setAge(22); + // repository.save(userJohn); + + userTom = new User(); + userTom.setFirstName("tom"); + userTom.setLastName("doe"); + userTom.setEmail("tom@doe.com"); + userTom.setAge(26); + // repository.save(userTom); + } + + private final String EURL_PREFIX = "http://localhost:8082/spring-security-rest-full/auth/users/espec?search="; + + @Test + public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(EURL_PREFIX + "'firstName:john,lastName:doe"); + final String result = response.body().asString(); + assertTrue(result.contains(userJohn.getEmail())); + assertTrue(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "firstName:john,lastName:doe"); + final String result = response.body().asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "firstName!john"); + final String result = response.body().asString(); + + assertTrue(result.contains(userTom.getEmail())); + assertFalse(result.contains(userJohn.getEmail())); + } + + @Test + public void givenMinAge_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "age>25"); + final String result = response.body().asString(); + + assertTrue(result.contains(userTom.getEmail())); + assertFalse(result.contains(userJohn.getEmail())); + } + + @Test + public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "firstName:jo*"); + final String result = response.body().asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "firstName:*n"); + final String result = response.body().asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "firstName:*oh*"); + final String result = response.body().asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "age>20,age<25"); + final String result = response.body().asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + private final RequestSpecification givenAuth() { + return RestAssured.given().auth().preemptive().basic("user1", "user1Pass"); + } +} diff --git a/xml/src/main/java/com/baeldung/xml/jibx/Person.java b/xml/src/main/java/com/baeldung/xml/jibx/Person.java index 54ce75e257..fbd7cde0a2 100644 --- a/xml/src/main/java/com/baeldung/xml/jibx/Person.java +++ b/xml/src/main/java/com/baeldung/xml/jibx/Person.java @@ -9,23 +9,14 @@ package com.baeldung.xml.jibx; import org.apache.commons.lang.builder.ToStringBuilder; public class Person extends Identity { - private String firstName; - private String lastName; + private String name; - public String getFirstName() { - return firstName; + public String getName() { + return name; } - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; + public void setName(String name) { + this.name = name; } public String toString() { diff --git a/xml/src/main/java/com/baeldung/xml/jibx/Phone.java b/xml/src/main/java/com/baeldung/xml/jibx/Phone.java index b24950289a..783f2ee6fb 100644 --- a/xml/src/main/java/com/baeldung/xml/jibx/Phone.java +++ b/xml/src/main/java/com/baeldung/xml/jibx/Phone.java @@ -2,26 +2,8 @@ package com.baeldung.xml.jibx; public class Phone { - private String countryCode; - private String networkPrefix; private String number; - public String getCountryCode() { - return countryCode; - } - - public void setCountryCode(String countryCode) { - this.countryCode = countryCode; - } - - public String getNetworkPrefix() { - return networkPrefix; - } - - public void setNetworkPrefix(String networkPrefix) { - this.networkPrefix = networkPrefix; - } - public String getNumber() { return number; } diff --git a/xml/src/main/resources/Order.xsd b/xml/src/main/resources/Order.xsd index 81f3e41628..cbb5bc7596 100644 --- a/xml/src/main/resources/Order.xsd +++ b/xml/src/main/resources/Order.xsd @@ -13,29 +13,6 @@ - - - - - - - - - - - - - - - - - - - diff --git a/xml/src/main/resources/customer-binding.xml b/xml/src/main/resources/customer-binding.xml index 54ce4a925f..c1a80366ef 100755 --- a/xml/src/main/resources/customer-binding.xml +++ b/xml/src/main/resources/customer-binding.xml @@ -14,14 +14,11 @@ - - + - - diff --git a/xml/src/test/java/com/baeldung/xml/jibx/CustomerTest.java b/xml/src/test/java/com/baeldung/xml/jibx/CustomerTest.java index c678ce8406..8b14277799 100644 --- a/xml/src/test/java/com/baeldung/xml/jibx/CustomerTest.java +++ b/xml/src/test/java/com/baeldung/xml/jibx/CustomerTest.java @@ -6,7 +6,6 @@ import org.jibx.runtime.IUnmarshallingContext; import org.jibx.runtime.JiBXException; import org.junit.Test; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; @@ -22,8 +21,7 @@ public class CustomerTest { InputStream inputStream = classLoader.getResourceAsStream("Customer1.xml"); Customer customer = (Customer) uctx.unmarshalDocument(inputStream, null); - assertEquals("Stefan", customer.getPerson().getFirstName()); - assertEquals("Jaeger", customer.getPerson().getLastName()); + assertEquals("Stefan Jaegar", customer.getPerson().getName()); assertEquals("Davos Dorf", customer.getCity()); } @@ -47,9 +45,7 @@ public class CustomerTest { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); InputStream inputStream = classLoader.getResourceAsStream("Customer1.xml"); Customer customer = (Customer) uctx.unmarshalDocument(inputStream, null); - - assertEquals("1", customer.getHomePhone().getCountryCode()); - assertEquals("234", customer.getHomePhone().getNetworkPrefix()); + assertEquals("234678", customer.getHomePhone().getNumber()); } diff --git a/xml/src/test/resources/Customer1.xml b/xml/src/test/resources/Customer1.xml index 3941563ffe..7f4fbc79af 100644 --- a/xml/src/test/resources/Customer1.xml +++ b/xml/src/test/resources/Customer1.xml @@ -2,18 +2,13 @@ 12345 - Stefan - Jaeger + Stefan Jaeger - 1 - 234 234678 - 1 - 234 234678 Davos Dorf